명령 출력의 각 줄에 쉘 명령을 적용하는 방법은 무엇입니까?


192

명령의 출력 (예 :)이 있다고 가정하십시오 ls -1.

a
b
c
d
e
...

echo각각에 명령 (예 :)을 적용하고 싶습니다 . 예 :

echo a
echo b
echo c
echo d
echo e
...

bash에서 가장 쉬운 방법은 무엇입니까?


3
ls -1여기에 예가있을 수 있지만의 출력을 구문 분석하는 것은 좋지 않다는 것을 기억하는 것이 중요합니다 ls. 다음을 참조하십시오 : mywiki.wooledge.org/ParsingLs
codeforester

답변:


217

사용하는 것이 가장 쉽습니다 xargs. 귀하의 경우 :

ls -1 | xargs -L1 echo

-L플래그는 입력이 제대로 읽어 보장합니다. 의 맨 페이지에서 xargs:

-L number
    Call utility for every number non-empty lines read. 
    A line ending with a space continues to the next non-empty line. [...]

24
ls-1파이프에서 자동으로 수행 됩니다.
추후 공지가있을 때까지 일시 중지되었습니다.

5
@Dennis, 그것처럼 보이지 않습니다 ls | xargs -L2 echols -1 | xargs -L2 echo두 개의 서로 다른 출력을 제공합니다. 전자는 모두 한 줄에 있습니다.
Alex Budovski

2
@ 알렉스 : 나는 같은 출력을 얻습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

6
xargs쉘 기능이나 쉘 내장 명령이 아닌 실행 파일 만 실행할 수 있습니다. 전자의 경우 가장 좋은 솔루션은 아마도 read루프에있는 솔루션 일 것입니다 .
pabouk

12
이 답변에 목적에 대한 설명이 포함되기를 바랍니다 -L1.
Wyck

164

각 줄에서 기본 접두사 작업을 사용할 수 있습니다.

ls -1 | while read line ; do echo $line ; done

또는보다 복잡한 작업을 위해 출력을 sed로 파이프 할 수 있습니다.

ls -1 | sed 's/^\(.*\)$/echo \1/'

1
sed 명령이 작동하지 않는 것 같습니다 sh: cho: not found a sh: cho: not found. ein echo를 sed 명령 또는 다른 것으로 사용하는 것처럼 보입니다 .
Alex Budovski

while루프의 경우 +1 cmd1 | while read line; do cmd2 $line; done. 또는 while read line; do cmd2 $line; done < <(cmd1)서브 쉘을 작성하지 않습니다. 이것은 sed명령 의 단순화 된 버전입니다 .sed 's/.*/echo &/'
추후 공지가있을 때까지 일시 중지되었습니다.

1
@Alex : 큰 따옴표를 작은 따옴표로 변경하십시오.
추후 공지가있을 때까지 일시 중지되었습니다.

5
"$line"단어 분할을 피하기 위해 while 루프를 인용하십시오 .
ignis

3
이스케이프 문자가 엉망이 read -r line되지 않도록 사용하십시오 read. 예를 들어 , 이스케이프를 잃은을 echo '"a \"nested\" quote"' | while read line; do echo "$line"; done제공합니다 "a "nested" quote". 우리가 예상대로 echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; done얻을 수 "a \"nested\" quote"있습니다. wiki.bash-hackers.org/commands/builtin/read
Warbo

9

for 루프를 사용할 수 있습니다 .

파일의 경우 *; 하다
   에코 "$ file"
끝난

문제의 명령이 여러 인수를 허용하면 xargs 를 사용 하는 것이 문제의 유틸리티를 여러 번 대신 한 번만 스폰하면되기 때문에 거의 항상 더 효율적입니다.


1
xargs의 적절하고 안전한 사용을 설명하는 것이 좋습니다. printf '%s\0' * | xargs -0 ...-그렇지 않으면 공백, 따옴표 등이있는 파일 이름으로 안전하지 않습니다.
Charles Duffy

8

GNU sed 인 경우 실제로 sed를 사용하여 수행 할 수 있습니다.

... | sed 's/match/command \0/e'

작동 방식 :

  1. 명령 일치로 대체 일치
  2. 대체 실행 명령
  3. 대체 라인을 명령 출력으로 교체하십시오.

환상적인. 나는 e 명령을 마지막 에 넣는 것을 잊었 지만 응답을 본 후에 그렇게했습니다. SED가 라인과 일치 할 때 1000에서 15000 사이의 임의의 ID를 추가하려고했습니다. cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
sgsi


2

xargs는 백 슬래시, 따옴표와 함께 실패합니다. 그것은 같은 것이어야합니다

ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."

xargs -0 옵션 :

-0, --null
          Input  items are terminated by a null character instead of by whitespace, and the quotes and backslash are
          not special (every character is taken literally).  Disables the end of file string, which is treated  like
          any  other argument.  Useful when input items might contain white space, quote marks, or backslashes.  The
          GNU find -print0 option produces input suitable for this mode.

ls -1개행 문자로 항목을 종료하므로 항목 tr을 널 문자로 변환합니다.

이 접근법은 수동으로 반복하는 것보다 약 50 배 느립니다 for ...( Michael Aaron Safyan 의 답변 참조) (3.55 대 0.066s). 그러나 찾기, 찾기, 파일에서 읽기 등의 다른 입력 명령 ( tr \\n \\0 <file) 또는 이와 유사한 작업을 수행해야합니다 xargs.


1

더 나은 결과 :

ls -1 | xargs -L1 -d "\n" CMD

더 좋지만 완벽하지는 않습니다. find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 command출력 ls -1이 모호한 경우를 처리 합니다. 당신이 각각에 대한 리드 를 원하지 않는 경우 -printf '%P\0'보다는 사용하십시오 . -print0./
Charles Duffy

1

예를 들어 목록에서 여러 명령을 실행하기 위해 gawk를 사용하고 싶습니다.

ls -l | gawk '{system("/path/to/cmd.sh "$1)}'

그러나 탈출 가능한 캐릭터의 탈출은 약간 털이 나올 수 있습니다.

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