我想制作一些目录树,并用带有随机内容的文本文件填充树的每一端。
这是我到目前为止所尝试的:
#!/bin/bash
set -e
echo "Generating test folders"
mkdir -p ./parent_{0..9}/child_{0..9}
head -c 100 /dev/urandom | xargs echo >> ./parent_{0..9}/child_{0..9}/test.txt
echo "done"
执行时,我收到此错误:
./gen-test.sh: line 8: ./parent_{0..9}/child_{0..9}/test.txt: ambiguous redirect
我做错了什么以及什么是完成这项任务的更明智的方法?
答案1
您做错的事情不起作用的原因是因为重定向和文件名生成是由 shell 处理的,而不是由 xargs 处理的。
当你写的时候
foo > foo.out
然后 shellfoo
将为您运行,捕获其标准输出,并将其写入foo.out
.
如果你跑
foo | xargs bar > bar.out
然后 shellfoo
将为您运行,捕获其标准输出,运行xargs
并将标准输出发送foo
到 的标准输入中xargs
。在某些时候,xargs
将运行,并将其在标准输入上收到的数据作为参数传递给它,并且它将以导致 的标准输出与 的标准输出无法区分的bar
方式执行此操作。 shell 将捕获该标准输出,并将其写入.bar
xargs
bar.out
您的参数./parent_{0..9}/child_{0..9}/test.txt
也由 shell 解释。它删除该参数,并将其替换为该模式生成的文件名,以便mkdir
命令行变得类似于(...
为了简洁而添加):
mkdir -p ./parent_0/child_0/test.txt ./parent_0/child_1/test.txt ./parent_0/child_2/test.txt ... ./parent_1/child_0/test.txt ... ./parent_9/child_9/test.txt
后来你跑
head -c 100 /dev/urandom | xargs # ...
echo
这意味着您读取 100 字节的随机数据,将其转换为by 的命令行参数xargs
,然后它将尝试输出该数据(这不太可能顺利,因为它是二进制数据,而且我们正在讨论这里是命令行)。
最后,shell 看到>>
,将其解释为附加重定向,后跟相同的模式;这意味着重定向变成
>> /parent_0/child_0/test.txt /parent_0/child_1/test.txt # and so on
但你不能那样做;您一次只能重定向到一个文件(这是您看到的“不明确的重定向”错误)。
最简单的解决方法是循环遍历文件:
for file in /pattern_0/child_0/test.txt; do
head -c 100 /dev/urandom > $file
done
因为任何使用 xargs 的解决方案都需要 echo 将命令行参数转换为标准输出,而只能使用 xargs 将相同的标准输出再次转换回命令行参数,这显然是低效的。