xargs 명령에서>를 사용하는 방법은 무엇입니까?


160

디렉토리의 모든 파일을 grep하고 그 grep의 출력을 별도의 파일에 쓸 수있는 bash 명령을 찾고 싶습니다. 내 생각 엔 이런 식으로 뭔가했을 것입니다

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

그러나 내가 아는 한 xargs는 큰 따옴표를 좋아하지 않습니다. 그러나 큰 따옴표를 제거하면 명령이 전체 명령의 출력을 일련의 개별 파일 대신 '{}'라는 단일 파일로 리디렉션합니다.

xargs를 사용 하여이 작업을 수행하는 방법을 아는 사람이 있습니까? 방금 xargs에 대한 내 문제를 설명하기 위해이 grep 시나리오를 예제로 사용했기 때문에 xargs를 사용하지 않는 솔루션은 나에게 적합하지 않습니다.

답변:


201

이 실수를하지 마십시오 :

sh -c "grep ABC {} > {}.out"

이것은 펑키 한 파일 이름을 포함하여 많은 조건에서 깨질 수 있으며 올바른 인용은 불가능합니다. 귀하 {}반드시 항상 피하기 코드 주입 버그의 명령에 하나의 완전히 별도의 인수합니다. 당신이해야 할 일은 이것입니다 :

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

에 적용 xargs됩니다 find.

그건 그렇고, -0옵션 없이 xargs를 사용하지 마십시오 (데이터 파괴에 대해 걱정하지 않는 매우 드물고 통제 된 일회성 대화 형 사용을 제외하고는).

또한 구문 분석하지 마십시오 ls. 이제까지. globbing 또는 find대신 사용하십시오 :http://mywiki.wooledge.org/ParsingLs

find재귀가 필요한 모든 것에 사용 하고 다른 모든 것을 위해 간단한 루프를 사용하십시오 .

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

또는 비 재귀 :

for file in *; do grep "$file" > "$file.out"; done

따옴표를 올바르게 사용하십시오.


찬성했지만 의심의 여지가 있습니다. xargswithout없이 사용 하지 마십시오 -0: 이것은 find출력 을 파이프로 파이프 할 때만 적용됩니다 xargs. 내가 xargs -a <input_file>어떻게 이것을 사용합니까? 같은 대부분의 명령 grep과 출력 \n이 아닌 \0.내가이 문제를 해결하기 위해 생각할 수있는 유일한 방법은 사용하는 것입니다 tr수정에 다시 아마를. 그러나 왜 함께 사용하는 것이 중요 -0합니까?
legends2k

3
@ legends2k 사용하지 않는 경우 때문에 -0, xargs당신의 파일 이름을 가지고 그 안에있는 모든 공간, 시세 및 백 슬래시를 깰 것입니다. xargs도구로 잊어 버려야 합니다. 줄이 있으면 bash 루프를 사용하여 줄을 반복하십시오. while read line; do <command> "$REPLY"; done < file-with-lines또는command | while ...
lhunath

1
와우, 그것에 대해 몰랐습니다. 자세한 내용에 감사드립니다! 따라서 이식성을 위해서 (모두 xargsGNU가 아니기 때문에 )로 xargs사용할 수 없다면 피해야합니다 -0. 감사합니다.
legends2k

1
이 특정 사용 사례에 대한 자세한 설명에 감사하지만 문제는의 출력을 리디렉션 하는 것 입니다. xargs항상 구문 분석 ls이나 사용을 포함하지는 않습니다 sh -c. 이것은 가장 작은 질문에 대한 답변은 아니지만 질문에 대한 첫 번째 Google 결과이며 혼란에 추가됩니다.
pandasauce

1
@Ihunath, 안녕하세요, 귀하의 답변이 저에게 효과적입니다. 그러나 자세한 설명이나 링크를 줄 수 xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}있습니까? 특히 포함 된 (큰) 따옴표 규칙과 끝에 "-"기호가 있습니다. 감사합니다
Scott Yang

40

없는 솔루션 xargs은 다음과 같습니다.

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

...와 같은 작업 수행 할 수 있습니다 xargs.

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

편집 : lhunath에 의해 언급 후 작은 따옴표가 추가됩니다 .


그는 xargs를 사용하고 싶다고 말했다. 나는 그것없이 솔루션을 게시했지만 xargs가 필요하다는 것을 알게되면 삭제했습니다.
Zifre

네가 옳아. 내가 답을 게시 한 이유는 전혀 수행하지 않는 것보다 대체 작업을하는 것이 더 낫다는 것이 었습니다. 원하는 답변 (즉, sh -c 트릭)을 찾을 수있는 올바른 길로 나를 안내했습니다.
Stephan202

14

나는 당신의 예가 단지 예이고 당신이 다른 것들을 위해 필요하다고 가정합니다. GNU Parallel http://www.gnu.org/software/parallel/ 이 당신의 구조 일 수 있습니다. 파일 이름에 \ n이 포함되어 있지 않으면 추가 인용 부호가 필요하지 않습니다.

ls | parallel "grep ABC {} > {}.out"

파일 이름이 \ n 인 경우 :

find . -print0 | parallel -0 "grep ABC {} > {}.out"

추가 보너스로 작업을 병렬로 실행할 수 있습니다.

자세한 내용은 소개 비디오를 참조하십시오 : http://pi.dk/1

10 초 동안 설치하면 전체 설치를 시도합니다. 실패하면 개인 설치; 실패하면 최소 설치 :

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

GNU Parallel이 설치되지 않은 서버로 서버를 이동해야하는 경우을 시도하십시오 parallel --embed.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.