일부 디렉토리 트리를 만들고 트리의 각 끝에 임의의 내용이 포함된 텍스트 파일을 채우고 싶습니다.
지금까지 시도한 내용은 다음과 같습니다.
#!/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
당신이 잘못하고 있는 것이 작동하지 않는 이유는 리디렉션 및 파일 이름 생성이 xargs가 아닌 쉘에 의해 처리되기 때문입니다.
당신이 글을 쓸 때
foo > foo.out
그러면 쉘이 foo
실행되어 표준 출력을 캡처하여 foo.out
.
당신이 달리면
foo | xargs bar > bar.out
그러면 쉘이 foo
자동으로 실행되어 표준 출력을 캡처하고 xargs
표준 출력 foo
을 xargs
. 어떤 시점에서는 실행되고 표준 입력으로 받은 데이터가 인수로 전달되며 xargs
결과 표준 출력이 의 표준 출력과 구별되지 않는 bar
방식으로 수행 됩니다. 쉘은 이 표준 출력을 캡처하여 기록합니다.bar
xargs
bar.out
귀하의 인수는 ./parent_{0..9}/child_{0..9}/test.txt
셸에서도 해석됩니다. 매개변수를 제거하고 이를 패턴에 의해 생성된 파일 이름으로 대체하여 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바이트의 임의 데이터를 읽고 이를 명령줄 인수로 변환한 xargs
다음 해당 데이터를 출력하려고 시도한다는 의미입니다(이진 데이터이고 여기서는 명령에 대해 이야기하고 있기 때문에 잘 진행되지 않을 것입니다).
마지막으로, 쉘은 이를 보고 >>
동일한 패턴이 뒤따르는 추가된 리디렉션으로 해석합니다.
>> /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를 사용하여 동일한 표준 출력을 다시 명령줄 인수로 다시 변환할 수 있으므로 이는 확실히 비효율적입니다.