36

My goal is deceptively simple (at least to me). I wish to take the output of ls -l or ls -lh and select just one field.

I am looking for this to be as bulletproof as possible, by which I mean, assume that filenames can have a variable number of spaces, not everything in the field has the same length, etc.

Bonus points for having a script that will take the name of the the field (or even just a field number), and then return the contents of the field.

I want to turn

enter image description here

into:

enter image description here

3 Answers 3

61

Try ls -l | awk '{print $7}'.

awk selects columns so it's perfect for this task.

6
  • 4
    As explained by @ormaaj: Do not rely on pieces of information being available in specific places with ls. The find command is tremendously helpful. Jul 18, 2012 at 10:02
  • @PaddyLandau How do I use the find command to print a file size in megabytes like I can with ls -l --block-size=M? Jul 4, 2019 at 18:08
  • @Benjamin — The ls command is not POSIX standard, so a script that depends on ls could break on different systems or even over time. See the answer by @ormaaj on this page for more details. One way to do what you ask is with a Bash loop. Here is an example. for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done. Of course, instead of echo, you'd use your processing. Jul 5, 2019 at 7:30
  • @PaddyLandau I just ended up piping the output of the find command to ... | xargs -d '\n' du -m which works just as well. Jul 5, 2019 at 16:13
  • @Benjamin You might want to look at the -exec option of find. Jul 5, 2019 at 19:08
25

Never parse ls. Use GNU find. Or if portability isn't important, stat(1).

find . -maxdepth 1 -printf '%Td\n'

For reading data other than lists of filenames line-by-line and splitting into fields, see: BashFAQ/001

There are no methods to reliably read a newline-delimited list of filenames that make sense under most circumstances.

2

You may fetch the specific column in shell like:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

or awk as shown in @Corey answer, cut -c44-45 would also work after adjustment (since ls has fixed columns) , or whatever else, however the main problem is that it won't be reliable and bulletproof (e.g. on Unix it may be $6, not $7, and it changes depending on arguments) making it not machine-friendly therefore it is not recommended to parse ls command at all.

The best is to use different available commands such as find or stat, which can provide relevant options to format the output as you need. For example:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

To return column of only days of modifications, try this example:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

It's worth to note that GNU stat could have different options to BSD stat, so it still won't be bulletproof across different operating systems.

4
  • 1
    +1 for mention that ls should not be parsed as well as for use of stat . date however is setup incorrectly. You should add --date=$ymd , since date by itself will print the current day, but the purpose here is to convert date format of the file Apr 10, 2016 at 4:37
  • The ls -la | cut -c32-33 command in total honesty is just completely unreliable, not only because of the possible pitfalls with the filenames, but simply because it depends on the usernames' length and on the files' size. The stat -c "%x" *.* command looks ok, but by using *.* you're restricing it only to filenames containing a dot. I guess the intention was to catch also hidden files; in that case you should enable globbing for dotfiles beforehand and use * instead of *.*: shopt -s dotglob; stat -c "%x" * | [...].
    – kos
    Apr 10, 2016 at 4:50
  • Ah and what Serg said also, you should add --date="$ymd" to the date command, otherwise it will print the current day of the month.
    – kos
    Apr 10, 2016 at 5:01
  • Thanks for the comments. I've addressed the issues and provided a better initial example.
    – kenorb
    Apr 10, 2016 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.