3 ms·
> This breaks for filenames with spaces. Useful things in bash: export IFS=$'\n' or export IFS=$'\n' for I in `$COMMAND` do $OTHER_COMMAND "${I}"
by simoncion 11y ago
> This breaks for filenames with spaces.
Useful things in bash:
export IFS=$'\n'
or
export IFS=$'\n'
for I in `$COMMAND` do
$OTHER_COMMAND "${I}"
done
or, generally:
find ./ -print0 | xargs -0 $COMMAND
- pdkl95 11y ago> export IFS Be careful exporting a changed IFS. That will inherit into child commands, which can cause unexpected breakage. A better model is to simply set IFS in the bash script (without export) or even better, as a one-off prefix to a command # leaves IFS set for following commands IFS=$'\n' $COMMAND # only sets IFS for one command IFS=$'\n' $COMMAND It is common to see saving/restoring IFS to protect against bugs elsewhere from a non-standard IFS: oldIFS="$IFS" IFS=$'\n' # ...stuff... IFS="$oldIFS" If you do this, a trap is a better idea to guarantee the restore happens. Better yet, let bash handle that for you automagically by using a local variable. cmd_with_nonstandard_ifs() { local IFS='\n' $COMMAND } cmd_with_nonstandard_ifs # IFS is back to normal here Also, unless you're using a really ancient version of bash, you shouldn't use backticks for command substitution. Use $() instead. # backticks need to be escaped when nested FOO="`basename "\`command_that_outputs_a_path\`"`" # much easier to read in the modern form FOO="$(basename "$(command_that_outputs_a_path)")" The thing is, you probably don't even need mess with IFS - shell globbing handles a lot of these things for you $ ls -1 a bc a b c d e ddd eee $ for file in * ; do echo "[$file]" ; done [a bc] [a b c d e] [ddd eee] and arguments be expanded correctly with "$@" show_args() { for arg in "$@" ; do echo "arg that supports spaces: [$arg]" done } show_args "foo bar" > find | xargs Of course, this is always a nice option that bypasses the need for bash. Minor suggestion: "find ." and "find ./" are identical.
- simoncion 11y agoAll good advice. I was intentionally making a correctness/terseness tradeoff. :) > ...and arguments be expanded correctly with "$@" That assumes that your bash is contained within a script, yes? It doesn't work for commands entered directly in a shell? > ...unless you're using a really ancient version of bash, you shouldn't use backticks for command substitution. I was -stupidly- unaware that backticks would nest. I always use $() when I want to nest command substitutions. > "find ." and "find ./" are identical. Oh, I know. I have the largely unjustifiable habit of always putting a path in a find invocation, as well as always spelling "the current directory" as ./ > > find | xargs > Of course, this is always a nice option that bypasses the need for bash. Don't forget -print0 and -0 if you expect to have to handle arguments that contain spaces! ;)
- pdkl95 11y ago> That assumes that your bash is contained within a script, yes? Or a function. (that is, anywhere the $1, $2, ... variables are available, as "$@" (must have the double-quotes!) just copies $1, $2, .. without changing the word splitting. > as well as always spelling "the current directory" as ./ That's actually a very good habit to be in a lot of other commands. It's unnecessary with find, but it's harmless either way.