내가 알고 싶은 정확히 무엇을 {} \;
하고 {} \+
와| xargs ...
않습니다. 설명과 함께이를 명확히하십시오.
아래 3 개의 명령은 동일한 결과를 실행하고 출력하지만 첫 번째 명령은 약간의 시간이 걸리며 형식도 약간 다릅니다.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
첫 번째는 file
명령에서 오는 모든 파일에 대해 명령을 실행하기 때문 find
입니다. 따라서 기본적으로 다음과 같이 실행됩니다.
file file1.txt
file file2.txt
그러나 후자의 2 -exec
명령은 아래와 같은 모든 파일에 대해 파일 명령을 한 번 실행합니다.
file file1.txt file2.txt
그런 다음 첫 번째 명령은 문제없이 실행되지만 두 번째 명령은 오류 메시지를 표시하는 다음 명령을 실행합니다.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
를 사용하는 명령의 {} \+
경우 오류 메시지가 표시됩니다.
find: missing argument to `-exec'
왜 그런 겁니까? 누구든지 내가 뭘 잘못하고 있는지 설명해 주시겠습니까?
답변
매뉴얼 페이지 (또는 온라인 GNU 설명서 ) 거의 모든 것을 설명합니다.
find -exec 명령 {} \;
각 결과에 대해 command {}
실행됩니다. 의 모든 항목은 {}
파일 이름으로 대체됩니다. ;
쉘이 해석하지 못하도록 슬래시가 접두어로 붙습니다.
find -exec 명령 {} +
각 결과는 추가 command
되고 나중에 실행됩니다. 명령 길이 제한을 고려하면이 명령이 나를 지원하는 매뉴얼 페이지와 함께 더 많이 실행될 수 있다고 생각합니다.
명령의 총 호출 수는 일치하는 파일 수보다 훨씬 적습니다.
매뉴얼 페이지에서 다음 인용문을 참고하십시오.
명령 줄은 xargs가 명령 줄을 빌드하는 것과 거의 같은 방식으로 빌드됩니다.
어떤 문자 사이에 허용되지 않습니다 이유 {}
와 +
공백을 제외하고. +
find는 인수가 명령에 추가되어야 함을 감지합니다 xargs
.
해결책
운 좋게도의 GNU 구현은 또는 더 긴 매개 변수 mv
를 사용하여 대상 디렉토리를 인수로 받아 들일 수 있습니다 . 사용법은 다음과 같습니다.-t
--target
mv -t target file1 file2 ...
귀하의 find
명령이된다 :
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
매뉴얼 페이지에서 :
-exec 명령;
명령을 실행하십시오. 0 상태가 반환되면 참. 찾을 다음 모든 인수는`; ‘로 구성된 인수가 될 때까지 명령에 대한 인수로 간주됩니다. 만난다. 문자열`{} ‘는 find의 일부 버전에서와 같이 단독 인 인수뿐만 아니라 명령에 대한 인수에서 발생하는 모든 곳에서 처리되는 현재 파일 이름으로 대체됩니다. 이 두 구조는 쉘에 의한 확장으로부터 보호하기 위해 이스케이프 (`\ ‘로)하거나 인용해야 할 수 있습니다. -exec 옵션 사용의 예는 EXAMPLES 섹션을 참조하십시오. 지정된 명령은 일치하는 각 파일에 대해 한 번씩 실행됩니다. 명령은 시작 디렉토리에서 실행됩니다. -exec 조치 사용과 관련하여 피할 수없는 보안 문제가 있습니다. 대신 -execdir 옵션을 사용해야합니다.
-exec 명령 {} +
-exec 조치의이 변형은 선택한 파일에서 지정된 명령을 실행하지만 명령 줄은 선택한 각 파일 이름을 끝에 추가하여 작성됩니다. 명령의 총 호출 수는 일치하는 파일 수보다 훨씬 적습니다. 명령 줄은 xargs가 명령 줄을 빌드하는 것과 거의 같은 방식으로 빌드됩니다. 명령 내에서`{} ‘의 인스턴스는 하나만 허용됩니다. 명령은 시작 디렉토리에서 실행됩니다.
답변
ZSH 셸을 사용하여 Mac OSX 에서 동일한 문제가 발생했습니다 .이 경우에 대한 옵션 이 없으므로 다른 솔루션을 찾아야했습니다. 그러나 다음 명령이 성공했습니다.-t
mv
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
비밀은 중괄호를 인용하는 것이 었 습니다 . 중괄호가 끝 부분에있을 필요가 없습니다.exec
명령 .
Ubuntu 14.04 ( BASH 및 ZSH 셸 사용)에서 테스트 했으며 동일하게 작동합니다.
그러나 +
표지판을 사용할 때 실제로 exec
명령 의 끝에 있어야하는 것 같습니다 .
답변
지원하지 않는 구현 이나 지원하지 않는 구현 에 find -iname ... -exec mv -t dest {} +
대한 표준 동등한 것은 셸을 사용하여 인수를 다시 정렬하는 것입니다.find
-iname
mv
-t
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "$@" /dest/dir/' sh {} +
를 사용 -name '*.[cC][pP][pP]'
하면 c
또는 의 대문자 버전을 결정하기 위해 현재 로케일에 의존하지 않아도됩니다 p
.
참고 +
반면에, ;
(포탄 물론 제외하지 않습니다 피해를 인용하지만 원하는 쉘이 그렇게 인용 할 필요가 없습니다 특별하지 않다 rc
가 지원하지 않는 \
인용 문 연산자로).
후행 /
인은 /dest/dir/
그 때문에입니다 mv
대신 이름을 변경의 오류와 함께 실패 foo.cpp
에 /dest/dir
단 한 곳 경우 cpp
파일이 발견되었고 /dest/dir
존재하지 않았거나 디렉토리 (또는 디렉토리에 대한 심볼릭 링크)가 아니었다.
답변
find . -name "*.mp3" -exec mv --target-directory=/home/d0k/Музика/ {} \+
답변
없음의 차이 +
와는 \;
역전한다. +
exec 명령 끝에 파일을 추가 한 다음 exec 명령을 실행하고 \;
각 파일에 대해 명령을 실행합니다.
문제는 탈출하거나 종료 할 필요 find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
가 find . -type f -iname '*.cpp' -exec mv {} ./test/ +
없다는 것입니다.+
xargs 나는 오랫동안 사용하지 않았지만 +처럼 작동한다고 생각합니다.