我正在使用 GNU sed 4.2.2,搜索后无法找出sed
在某些情况下行为奇怪的原因:
我有一个包含以下内容的目录:
foofile.txt
barfile.txt
bazfile.txt
config/
情况1
sed -i 's/foo/bar/g' *.txt
这正如我所期望的那样。它将三个常规文件中的所有“foo”替换为“bar”。
案例2
sed -i 's/foo/bar/g' *
sed: couldn't edit config: not a regular file
barfile.txt
它在和中将“foo”替换为“bar” bazfile.txt
,但在 中则不然foofile.txt
。我假设它会遍历按字母顺序扩展的文件列表*
,当它遇到config/
错误并退出时。有没有办法sed
忽略错误并继续处理文件?
案例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
有人可以解释一下为什么sed
会这样吗?为什么给它一个输入文件时却说没有输入文件?
我知道我可以使用以下内容,但我问为什么 sed 会这样做,而不是如何解决这个用例。
find . -maxdepth 1 -type f -exec sed -i 's/foo/bar/g' {} \;
答案1
案例2:
使用以下命令避免该目录
find
:sed -i 's/foo/bar/g' $(find . -maxdepth 1 -type f)
案例3:
问题在于
<"$file"
循环中,它将文件转换为流,因此sed
永远看不到文件名。只需删除它<
:for file in $(find . -maxdepth 1 -type f); do sed -i 's/foo/bar/g' "$file" done
答案2
这是正常行为。在这两种情况下sed
都以error code 4
... per退出info sed
:
4
An I/O error, or a serious processing error during runtime,
GNU 'sed' aborted immediately.
在这两种情况下,消息都是不言自明的。不确定什么不清楚,但为了记录:第一次它出错是因为它无法编辑目录,第二次它抱怨是因为它无法stdin
就地编辑,它需要一个文件(即删除之前的重定向$file
)
正确的方法find
正如您所指出的,通过使用 glob 来执行此操作-exec ...
,您必须使用循环并在运行之前测试输入是否为常规文件sed
。或者,如果您是zsh
用户,您可以简单地执行以下操作:
sed -i 's/foo/bar/g' *(.)