[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Loop with files coming through sorted by name
From: |
Seth David Schoen |
Subject: |
Re: Loop with files coming through sorted by name |
Date: |
Fri, 15 Oct 2021 19:34:56 -0700 |
tolugboji via writes:
> I have a list of image files and want to pass them in a loop with files
> coming through sorted by name.
>
> Have seen this approach
>
> for
>
> filename
>
> in
>
> `ls | sort -n`
>
> Are backticks still a good way to do this, as currently things are shifting
> towards $().
Backticks are no longer considered good shell style and $() is always
preferred nowadays.
Apart from that, there's the issue about filenames that may contain
spaces. While Unix style discourages spaces in filenames (partly
because of the popularity of these loops, no doubt!), they are
completely possible and permissible at the OS level and not necessarily
uncommon. If you do the bare
for filename in $(ls | sort -n); do
form, then filenames with spaces will be handled incorrectly. Consider
$ touch "uh oh"
$ touch "this won't work"
$ for i in $(ls | sort); do cat $i; done
cat: this: No such file or directory
cat: "won't": No such file or directory
cat: work: No such file or directory
cat: uh: No such file or directory
cat: oh: No such file or directory
There are tricks available involving changing the bash IFS (input field
separator) variable, as well as the form
for filename in "$(ls | sort -n)"
but a further thing to ponder is that newline characters are also
officially valid in filenames (!). If a filename contained a newline,
it would still break in this format -- the sort command itself would
consider the filename to be multiple lines.
Shell globbing is safe in for loops (in the sense that "for i in *" works
regardless of what kind of whitespace or control characters are in the
filenames), but it still doesn't have the interaction that you want
with the sort command, because it will still consider a newline to be
a delimiter between records.
Typically people will suggest instead using the find command, either
with the -exec flag or with the -print0 flag. This is extensively
described in
https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find
A disadvantage there is that the command run by the -exec can only be
a single command, not a bunch of shell scripting or even a pipeline.
A cool thing with -print0 is that you can, in fact, combine it nicely
with sort using the -z option, like
find . -type f -name '*.ogg' -print0 | sort -z -n | xargs -r -0 ogg123
will work to sort .ogg files in numeric order and them play them back,
regardless of whitespace in the filenames. There is also grep -z,
which works with the null-terminated lines produced by -print0.
- Loop with files coming through sorted by name, tolugboji, 2021/10/15
- Re: Loop with files coming through sorted by name,
Seth David Schoen <=
- Re: Loop with files coming through sorted by name, Seth David Schoen, 2021/10/15
- Re: Loop with files coming through sorted by name, Greg Wooledge, 2021/10/16
- Loop with files coming through sorted by name, tolugboji, 2021/10/16
- Re: Loop with files coming through sorted by name, Daniel Mills, 2021/10/16
- Loop with files coming through sorted by name, tolugboji, 2021/10/16
- Re: Loop with files coming through sorted by name, Daniel Mills, 2021/10/16
- Re: Loop with files coming through sorted by name, Dennis Williamson, 2021/10/16