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 에서 동일한 문제가 발생했습니다 .이 경우에 대한 옵션 이 없으므로 다른 솔루션을 찾아야했습니다. 그러나 다음 명령이 성공했습니다.-t
mv
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
비밀은 중괄호를 인용하는 것이 었 습니다 . exec
명령 끝에 중괄호를 사용할 필요가 없습니다 .
I tested under Ubuntu 14.04 (with BASH and ZSH shells), it works the same.
However, when using the +
sign, it seems indeed that it has to be at the end of the exec
command.
The standard equivalent of find -iname ... -exec mv -t dest {} +
for find
implementations that don't support -iname
or mv
implementations that don't support -t
is to use a shell to re-order the arguments:
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "$@" /dest/dir/' sh {} +
By using -name '*.[cC][pP][pP]'
, we also avoid the reliance on the current locale to decide what's the uppercase version of c
or p
.
Note that +
, contrary to ;
is not special in any shell so doesn't need to be quoted (though quoting won't harm, except of course with shells like rc
that don't support \
as a quoting operator).
The trailing /
in /dest/dir/
is so that mv
fails with an error instead of renaming foo.cpp
to /dest/dir
in the case where only one cpp
file was found and /dest/dir
didn't exist or wasn't a directory (or symlink to directory).
no, the difference between +
and \;
should be reversed. +
appends the files to the end of the exec command then runs the exec command and \;
runs the command for each file.
The problem is find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
should be find . -type f -iname '*.cpp' -exec mv {} ./test/ +
no need to escape it or terminate the +
xargs I haven't used in a long time but I think works like +.
참고URL : https://stackoverflow.com/questions/5607542/why-does-find-exec-mv-target-not-work
'code' 카테고리의 다른 글
데이터베이스 테이블의 열에 목록을 저장하는 방법 (0) | 2020.08.25 |
---|---|
Access-Control-Allow-Origin 헤더를 추가하는 방법 (0) | 2020.08.25 |
자바 스크립트 객체를 검사하는 방법 (0) | 2020.08.24 |
목록 항목의 대체 배경색 (0) | 2020.08.24 |
자바 스크립트의 클래스에서 상속하는 방법은 무엇입니까? (0) | 2020.08.24 |