Linux에서 명령 출력 행을 다른 명령으로 실행

Linux에서 명령 출력 행을 다른 명령으로 실행

나는 다음 명령을 실행하고 있습니다 :

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.

관련 정보