나는 다음 명령을 실행하고 있습니다 :
find ./ -type f -printf "wc -l \"%p\"\n"
그러면 다음과 같은 출력이 제공됩니다.
wc -l "ANLS 457567.pl"
wc -l "ANLS 457567.pl"
이제 전체 라인을 다른 명령으로 실행하고 싶습니다.
이 목표를 어떻게 달성할 수 있나요?
나는 이를 사용하여 xargs
출력을 매개변수로 다른 명령에 전달할 수 있다는 것을 알고 있지만 호기심으로 (명령 출력 줄을 다른 명령으로 실행)것이 가능하다.
답변1
이와 같은 명령을 셸에 파이프할 수 있지만 모든 글로브, 변수 및 기타 항목이 확장되므로 매우 문제가 발생할 수 있습니다.
예를 들어 별표( *
, glob ) 또는 달러 기호( $
, 변수 및 명령 확장)가 포함된 파일 이름은 문제를 야기합니다. 모든 내용을 올바르게 인용했는지 확인해야 하며 일반적으로 파일 이름 자체에 따옴표가 포함될 수 있으므로 쉽지 않습니다.
find
그러나 외부 명령 자체를 실행할 수 있는 경우에는 다음과 같습니다 .
find ./ -type f -exec wc -l {} \;
the는 {}
현재 파일 이름으로 대체되며 후행(인용부호) 세미콜론이 필요합니다.
적어도 일부 버전은 find
여러 파일 이름이 지정된 명령을 한 번에 실행하는 데 사용할 수 있는 대체 형식을 지원하여 많은 실행 시간을 절약합니다.
find ./ -type f -exec wc -l {} \+
답변2
그냥 쉘의 STDIN에 전달하세요:
find ./ -type f -printf "wc -l \"%p\"\n" | sh
또는 쉘이 프로세스 대체를 지원하는 경우 다음을 수행하십시오 <()
.
sh <(find ./ -type f -printf "wc -l \"%p\"\n")
단지 find
:
find ./ -type f -exec wc -l {} +
답변3
이 경우의 실제 해결 방법은 @ilkkachu 댓글을 참조하세요. 그러나 그 이상으로 쉘은 각 행을 실행하기 전에 변수를 확장하므로
find ./ -type f -printf "wc -l %p\n" | while read line; do
$line
done
(예를 들어 공백과 같이 파일 이름에 특수 문자가 포함되지 않는 한) 잘 작동합니다.
주위에 따옴표가 없고 $line
따옴표도 없습니다 %p
. 그건 우리 때문이야생각하다쉘은 실행하기 전에 행을 단어로 분할합니다. $line
마치 사용자가 직접 작성하는 것처럼 단어를 명령 및 인수로 처리합니다. 그렇기 때문에 공백이 작동하지 않습니다.
이는 내장 쉘을 사용하여 방지할 수 있습니다 eval
.진짜따옴표를 포함하여 쉘에 명령을 입력한 것처럼 작동합니다(지금은 다시 표시됨).
find ./ -type f -printf "wc -l \"%p\"\n" | while read line; do
eval $line
done
마지막 방법은 모든 경우에 작동하지만 여전히 좋은 방법은 아닙니다. eval
최후의 수단이 되어야 합니다. 나는 이러한 옵션이 작동한다는 것을 알려드리기 위해 이러한 옵션을 포함시켰지만 일반적 -exec
으로 find
.