이 xargs 명령이 작동하지 않는 이유는 무엇입니까?


14

모든 .sh 확장자를 삭제하고 싶었습니다.

ls *.sh | xargs -I {} mv {} `basename {} .sh`

그러나 작동하지 않으면 basename변경되지 않은 파일 이름을 반환 하는 것처럼 작동 합니다.

왜 그런 식으로 작동합니까?

예를 들어 다음과 같이 작동합니다.

ls *.sh | xargs -I {} echo `basename {}.jpg .jpg`;

편집 :

솔루션 : 작은 따옴표 `basename ...`는 명령이 실행되기 전에 쉘이 평가 하지 못하게 합니다.

ls *.sh | xargs -I {}  sh -c 'mv {} `basename {} .sh`'

답변:


12

파이프 라인이 실행되기 전에 basename 명령이 실행되기 때문입니다. 이 작업을 수행하려면 기본 이름을 실행하기 위해 xargs가 필요합니다 sh -c. 예를 들면 다음 과 같습니다.

ls *.sh | xargs -L1 sh -c 'basename $1 .sh' dummy

노트:

  • xargs파일 이름을 삽입 할 위치를 알려주지 않으면 명령 줄 끝에 추가됩니다.
  • -L1스위치 나 이에 상응하는 기능을 사용해야 하므로 xargs인수 하나만 전달합니다 sh.
  • 출력을 사용하면 원하지 않는 효과ls 가있을 수 있습니다 .

편집하다

TechZilla 덕분에 더 이상 사용되지 않는 옵션 제거


3
기본적으로 -i옵션에 해당하지 않는 한 첫 번째 요지는 정확하지 않지만 해당 '클래식'옵션은 더 이상 사용되지 않습니다. 예를 들어, 하나의 옵션 / 라인 만 사용하려면 새로운 POSIX 매뉴얼 페이지를 권장 -L1합니다. 의 이전 비헤이비어를 호출하려면 -i페이지에서 -I'{}'옵션을 권장합니다 .
JM Becker

따라서 실제로는 ''대신 ''기호입니다. 나는 '의 쉘 평가를 방해한다고 생각합니다. 내 편집 내용을 참조하십시오.
majkinetor

@ TechZilla : 수정 해 주셔서 감사합니다. @ majkinetor : 예, 아니오, 평가를 지연해야하지만 백틱 (`)을 사용할 수 있다고 생각하지 않습니다.
Thor

1
@ majkinetor : 아, 나는 당신이 지금 무엇을 의미하는지 봅니다. 이런 식으로 파일의 이름을 바꾸려면 다음과 같이 사용 rename하십시오 rename 's/\.sh//' *.sh. 드라 이런 ( -n)으로 먼저 시도하십시오 .
Thor

1
@majkinetor : rename훌륭하고 간단하게 작동하지만 배포에 따라 다릅니다. RHEL과 데비안 기반 배포판은 서로 다른 rename명령을 제공 하므로 크로스 디스트로 스크립트를 작성할 때 명심해야합니다.
JM Becker

4

귀하의 질문에 대해 잘 모르겠습니다. 실제로 첫 번째 줄이 왜 작동하지 않는지 묻고 있습니까? 아니면 모든 .sh 파일의 이름을 바꾸는 적절한 방법을 찾고 있습니까?

가장 깨끗한 방법이라고 가정하기 전에 전에 명령 옵션을 준비하는 것을 선호합니다 xargs. .sh 파일 확장자를 제거하기 위해 종종이 접근법을 고려합니다.

 find -maxdepth 1 -type f -iname '*.sh'  | sed 'p;s_.sh$__' | xargs -L2 mv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.