[linux] find -exec mv {} ./target/ + 작동하지 않는 이유는 무엇입니까?

내가 알고 싶은 정확히 무엇을 {} \;하고 {} \+| 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 에서 동일한 문제가 발생했습니다 .이 경우에 대한 옵션 이 없으므로 다른 솔루션을 찾아야했습니다. 그러나 다음 명령이 성공했습니다.-tmv

find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;

비밀은 중괄호를 인용하는 것이 었 습니다 . 중괄호가 끝 부분에있을 필요가 없습니다.exec명령 .

Ubuntu 14.04 ( BASHZSH 셸 사용)에서 테스트 했으며 동일하게 작동합니다.

그러나 +표지판을 사용할 때 실제로 exec명령 의 끝에 있어야하는 것 같습니다 .


답변

지원하지 않는 구현 이나 지원하지 않는 구현 에 find -iname ... -exec mv -t dest {} +대한 표준 동등한 것은 셸을 사용하여 인수를 다시 정렬하는 것입니다.find-inamemv-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 나는 오랫동안 사용하지 않았지만 +처럼 작동한다고 생각합니다.


답변