I am using GNU sed 4.2.2 and after searching cannot find out the reason sed
behaves oddly in some situations:
I have a directory with the following:
foofile.txt
barfile.txt
bazfile.txt
config/
Case 1
sed -i 's/foo/bar/g' *.txt
This works as I expect. It replaces all the "foo"s with "bar"s in the three regular files.
Case 2
sed -i 's/foo/bar/g' *
sed: couldn't edit config: not a regular file
It replaces "foo" with "bar" in barfile.txt
and bazfile.txt
, but not in foofile.txt
. I assume it goes through the list of files expanded from the *
alphabetically, and when it hits config/
it errors and exits. Is there a way to have sed
ignore errors and continue processing files?
Case 3
for file in $(find . -maxdepth 1 -type f); do sed -i 's/foo/bar/g' <"$file"; done
sed: no input files
sed: no input files
sed: no input files
Could someone please explain why sed
does this? Why does it say there's no input file when it's being given one?
I know that I can use the following but I'm asking why sed acts this way, not how do I solve this one use case.
find . -maxdepth 1 -type f -exec sed -i 's/foo/bar/g' {} \;
Best Answer
It's normal behavior. In both cases
sed
exits witherror code 4
... perinfo sed
:and in both cases the messages are self-explanatory. Not sure what's unclear but for the record: the first time it errors out because it cannot edit a directory and the second time it complains because it cannot edit
stdin
in-place, it needs a file (i.e. remove that redirect before$file
)The proper way to do this with
find
is, as you noted, via-exec ...
With globs, you'll have to use a loop and test if input is a regular file before running
sed
. Or, if you're azsh
user, you can simply do: