8

I've seen many questions and answers here using a construction along the lines of

list_dir=`ls -t /path/to/dir/`
for i in $list_dir; do

or

ls -t | while read i; do

Now, I know that you shouldn't use ls in scripts because it breaks easily; but I can't find a better way of operating on files in order from last-modified to most-recently-modified (or vice versa).

I can use something like:

find . -type f -printf '%T@ %p\n' | sort -n | cut -d ' ' -f 2- | while read i; do...

...but this will still break with any files that have newlines in their names, and is much uglier to boot. Is there a better way?

2 Answers 2

8

"Don't use ls in scripts" is a problem with POSIX ls "only"; for GNU ls see --quoting-style=.

GNU sort solves the problem with --zero-terminated.

If it must be compatible then you could use find ... -exec for passing one file name at a time to a script which does the escaping. If at least bash is available:

start cmd:> testfunc () { echo "${1//$'\n'/\n}"; }
start cmd:> testfunc a$'\n'b
a\nb
7
  • Ahh, --zero-terminated - thank you for that, I wish I could give you even more points!
    – evilsoup
    May 27, 2013 at 16:38
  • ...OK, I'm a little confused by info ls: if I wanted a bulletproof script with ls, which --quoting-style should I use?
    – evilsoup
    May 27, 2013 at 16:48
  • @evilsoup I think --quoting-style=escape is the way to choose. May 27, 2013 at 16:57
  • Now, to create some files with newlines in their names to test it :P
    – evilsoup
    May 27, 2013 at 17:05
  • 1
    Also: I stumble upon a extreme case where ever GNU ls --quoting-style fail (for parsing purposea) because it quote filenames only: when you have a space in a group name. Ok, its a very strage case, but it appen in cygwin bash shell, here you have group names like Domain Users.
    – DavAlPi
    Jun 20, 2013 at 9:23
5

The easiest way by far is to use zsh. The glob qualifier om sorts matches in reverse chronological order; use Om for chronological order.

for x in /path/to/dir/*(Nom); do …

The N glob qualifier causes the pattern to expand to an empty list if the directory is empty. Make this *(DNom) to match dot files.

1
  • 1
    Dang, this is the first time I've been tempted to bother looking at other shells - that's very nice.
    – evilsoup
    May 27, 2013 at 23:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .