Macos 执行递归查找并替换为sed只会更改第一个文件
我试图递归搜索当前目录,在找到的每个Macos 执行递归查找并替换为sed只会更改第一个文件,macos,sed,find,exec,xargs,Macos,Sed,Find,Exec,Xargs,我试图递归搜索当前目录,在找到的每个.txt文件的第一行执行sed替换 在MacOS上运行以下两个命令之一: find . -name "*.txt" -exec sed -i '' '1 s/([^()]*)//g' {} + 结果也是一样的。只有找到的“第一个”文件才对其执行了sed操作。这似乎是因为sed-i''1s/([^()]*])//g'中的1。奇怪的是,即使这只导致使用第一个文件,它仍然只在该文件的第一行执行sed替换;它应该这样做 如果我将命令更改为此 find . -nam
.txt
文件的第一行执行sed替换
在MacOS上运行以下两个命令之一:
find . -name "*.txt" -exec sed -i '' '1 s/([^()]*)//g' {} +
结果也是一样的。只有找到的“第一个”文件才对其执行了sed
操作。这似乎是因为sed-i''1s/([^()]*])//g'
中的1
。奇怪的是,即使这只导致使用第一个文件,它仍然只在该文件的第一行执行sed替换;它应该这样做
如果我将命令更改为此
find . -name '*.txt' -print0 | xargs -0 sed -i '' '2 s/([^()]*)//g'
仍然只是更改了第一个文件,但现在第二行有替换文件。那么,我的问题是,为什么这似乎只影响
find . -name '*.txt' -print0
编辑以进行澄清
我应该澄清我所说的只有“第一个”文件通过一步一步地重新创建问题来执行sed操作的确切含义。首先,
这是文件夹层次结构(注意“文件夹1”中的空格):
每个.txt
文件都只包含一行:
这个应该留下(这个应该走)
当运行上述任一命令时,更改的是文件test2.txt
,问题是它是唯一更改的文件
现在,这些文件包含以下内容:
test1.txt:这个应该保留(应该保留)
test2.txt:这应该保持不变
test3.txt:这个应该保留(这个应该消失)
test4.txt:这个应该保留(这个应该消失)
我相信这是因为命令的第一部分,例如
find . -name '*.txt' -print0
给出以下内容(每个内容由一个\0
空字符分隔)
通过随机更改文件夹和文件名,可以清楚地看出,它始终是上述\0
分隔列表中更改的第一个文件
所以问题仍然存在,是什么原因阻止了sed在所有文件上被调用
谢谢 我想关于第一个命令的问题由Beta回答,让我回答第二个 尝试将
-t
(测试)选项置于xargs
并查看命令行
扩展为:
find . -name '*.txt' -print0 | xargs -0 -t sed -i '' '1 s/([^()]*)//g'
它将输出如下内容:
sed -i '' 1 s/([^()]*)//g ./test1.txt ./test2.txt ./test3.txt ./test4.txt
xargs
的默认行为是执行指定的命令
(sed
在本例中)立即使用从标准中读取的所有参数
输入。此外,
sed
不会在多个输入文件和s
命令之间重置行号
以上内容仅适用于第一个文件
您可以使用-l1
选项更改xargs
的行为:
find . -name '*.txt' -print0 | xargs -0 -l1 -t sed '1 s/([^()]*)//g'
输出:
sed -i '' 1 s/([^()]*)//g ./test1.txt
sed -i '' 1 s/([^()]*)//g ./test2.txt
sed -i '' 1 s/([^()]*)//g ./test3.txt
sed -i '' 1 s/([^()]*)//g ./test4.txt
然后
sed
将按预期工作。您认为'
的作用是什么?你登记seds帮助了吗?如果你移除它会发生什么?MacOs,GNU,您正在使用哪个sed?@Yunnosch我认为有必要使用“”来阻止MacOs创建已编辑文件的备份副本?因此,通过使用“”,我强迫sed以isIf的形式编辑每个文件,如果我正确地告诉您使用MacOs sed,那么我建议您在您的问题中明确地提到这一点。试着找到一个标记来反映这一点。第一个命令末尾的+
是什么意思?我想如果你用\代码>相反,它将按预期工作。我不确定为什么xargs
版本不起作用。谢谢,但在我解释它为什么起作用之前,我不会将其作为答案发布。我对xargs
之谜有一个部分答案。。。
sed -i '' 1 s/([^()]*)//g ./test1.txt ./test2.txt ./test3.txt ./test4.txt
find . -name '*.txt' -print0 | xargs -0 -l1 -t sed '1 s/([^()]*)//g'
sed -i '' 1 s/([^()]*)//g ./test1.txt
sed -i '' 1 s/([^()]*)//g ./test2.txt
sed -i '' 1 s/([^()]*)//g ./test3.txt
sed -i '' 1 s/([^()]*)//g ./test4.txt