I want to loop over files with
for f in `grep -rsl "foo" . `: do sed -i -- "s/foo/bar/g" $f; done;
But since filenames contain spaces, a filename is split whenever a space is found.
How can I pass the filename with its spaces to the do
block?
For dealing with difficult file names, it is best to separate the file names with NUL characters. GNU grep
supports this with the --null
option and xargs
supports this with the -0
option. Thus, try:
grep --null -rslZ "foo" | xargs -0 sed -i -- "s/foo/bar/g"
grep --null -rslZ "foo" | while IFS= read -r -d $'\0' file
do
sed -i -- "s/foo/bar/g" "$file"
done
--null
which is supported by both GNU and FreeBSD. The OpenBSD man page however does not list any support for NUL.
for
for looping over filenames with spaces.
for f in *.txt
. Don't try to do anything fancy there—it'll almost certainly fail.
grep
s and the like: find . -type f -print0 | xargs -0 grep -sl 'foo' | tr '\n' '\0' | xargs -0 sed -i -e 's/foo/bar/g' --
You can safely forget about for for looping over filenames with spaces.
Not necessarily...
IFS=$'\n' && for NAV in `ps aux | egrep -o 'Google Chrome' | sort | uniq`; do
open -a "$NAV" http://www.google.com
done
find . -type f -exec grep -qF foo {} \; -exec sed -i 's/foo/bar/g' {} \;