我有 3 个文件:a.txt
、b.txt
和c.txt
.我想创建 3 个文件:a.test
,b.test
并c.test
包含简单文本abracadabra
.
基本上,重点是.test
为每个.txt
文件创建文件,并用一些文本填充它们。我正在尝试用xargs
它来做到这一点。
anlx2626> ls
a.txt b.txt c.txt
anlx2626> ls *.txt | awk -F'.txt' '{print $1}' | xargs -I {} echo "abracadabra" > {}.test
anlx2626> ls *.test
ls: No match.
有人能指出为什么使用{}
占位符进行逐行管道不能按我期望的方式工作吗?
答案1
在此代码中:
xargs -I {} echo "abracadabra" > {}.test
xargs 根本看不到重定向运算符>
:它将由您的 shell 进行解释,创建一个名为 .xargs 的文件
{}.test
。
使用 xargs 执行您要求的操作的一种方法是这样,它让 sh 解释重定向运算符:
xargs sh -c 'for i do echo abracadrabra > "$i"; done' sh
但你可能最好根本不使用 xargs,其他答案解释了如何做。
答案2
awk
可以输出文本,不需要echo
或xargs
。您的方法对于包含多个点的文件名存在问题,例如foo-1.2.txt
.
对于包含换行符的文件名或者存在名称以.txt
.
这一次,我将在这里使用循环,例如使用 zsh:
(set -o noclobber; for f (*.txt(N)) echo abracadabra > $f:r.test)
或者 POSIXly:
(set -o noclobber
for f in *.txt; do
echo abracadabra > "${f%.*}.test"
done)
这noclobber
是为了避免覆盖已经存在的文件。请注意,它忽略了隐藏文件。如果没有txt
文件,POSIX sh 变体将创建一个*.test
文件。
答案3
尽管这个问题已经得到了充分的回答,但我只是添加这个以展示另一种方式:
while IFS= read -r
do
echo abracadabra > "${REPLY}.test"
done < <(find . -maxdepth 1 -name "*.txt" -exec basename -s .txt {} \;)
这里find用于列出文本文件。maxdepth
用于阻止 find 递归到子文件夹中。basename -s .txt
用于从一开始就删除 txt 扩展名,因为除了列出名称之外,我们根本不需要它。在 while 循环中,我们只需使用不带扩展名的名称,并使用字符串替换来添加.test
扩展名,同时回显到文件。请注意,我们使用了 的默认变量while
,即$REPLY
。
答案4
for l in $(ls *.txt); do echo "abrakadabra" > $l; done