제외하여 찾아 이동

제외하여 찾아 이동

find와 mv를 모두 사용해야합니다.

요구 사항: 모든 *.xml 파일을 찾아야 하지만, 예금.xml을 제외하고 다른 폴더로 이동해야 합니다(상당히 간단함).

내 시도:

mv `find ./*.xml '!' -type d | fgrep -v deposit.xml` ./Archive

파일이 있으면 잘 작동하고, 파일이 없으면 다음 오류가 발생합니다.

mv: missing destination file operand after `./Archive'
Try `mv --help' for more information.*

답변1

ls또는 출력을 구문 분석하는 것은 일반적 find으로 어떤 문자가 파일 이름의 일부인지 구분 기호인지 알 수 없기 때문에 좋지 않은 생각입니다. 파일 이름을 제어하지 않으면 공격자가 파일 이름을 위조하여 스크립트가 임의 코드를 실행할 수 있게 하는 보안 취약점이 될 수 있습니다. 바라보다공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?. 그러나 귀하의 경우에는 괜찮을 수 있습니다. 특히 파일이 일종의 소스 코드 트리인 것처럼 보이고 파일 이름에 일반적으로 "이국적인" 문자가 없고 특히 공백이 없는 경우에는 그렇습니다.

그래도 강력한 명령을 사용하는 것은 실제로 어렵지 않습니다. 핵심 아이디어는 구문 분석 대신 find호출을 수행하는 것입니다 . 다음 명령은 현재 디렉터리 및 하위 디렉터리에서 재귀적으로 이동합니다.mvfind.xml

find . ! -type d -name '*.xml' ! -name deposit.xml -exec mv {} ./Archive \;

작업 속도를 조금 높이려면 mv중간 셸을 실행하여 호출을 쌍으로 그룹화할 수 있습니다.

find . ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

하위 디렉터리를 순회하지 않고 현재 디렉터리에서만 파일을 이동하려면 find반복하지 않도록 표시해야 합니다. find구현에서 이 옵션을 지원 하는 경우 -maxdepth:

find . -maxdepth 1 ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

그렇지 않으면:

find . -name . -o -type d -prune -o -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

쉘이 ksh인 경우 확장 glob을 사용할 수 있습니다. 이는 를 사용하는 것보다 쉽지만 find이식성이 떨어집니다. 현재 디렉터리에서 파일을 이동합니다.

mv !(deposit).xml Archive/

ksh93에서는 하위 디렉터리에서 파일을 이동할 수도 있습니다.

set -o globstar
mv **/!(deposit).xml Archive/

Bash에서도 이 모드를 사용할 수 있지만 먼저 실행 !(…)해야 합니다 . shopt -s extglob이 모드를 사용하려면 먼저 실행 **/해야 하며 , bash 4.2까지는 디렉터리 외에도 디렉터리에 대한 심볼릭 링크도 통과된다는 shopt -s globstar점에 유의하세요 .**/

shopt -s extglob globstar
mv **/!(deposit).xml Archive/

!(…)zsh에서는 setopt ksh_glob. 또는 를 실행한 후 zsh의 구문을 사용할 수 있습니다 setopt extended_glob. 어느 쪽이든 재귀 순회 구문을 사용할 수 있습니다.

setopt extglob
mv **/(^deposit).xml Archive/

답변2

찾기 명령을 사용합니다.

find ./*.xml -type f ! -name "deposit.xml" -exec mv {} ./Archive ';'

"xargs" 명령과 함께 "find"를 사용하십시오:

find ./*.xml -type f ! -name "deposit.xml" | xargs -I {} mv {} ./Archive

"for" 루프와 "find" 명령을 사용하세요.

for f in $(find ./*.xml -type f ! -name "deposit.xml"); do mv ${f} ./Archive; done

게다가 에 따르면GNU/Linux 시스템용 매뉴얼 페이지, "mv" 명령에는 "-t | --target-directory" 옵션이 있습니다. 따라서 다음과 같이 "xargs"와 함께 사용할 수 있습니다.

find ./*.xml -type f ! -name "deposit.xml" | xargs mv -t ./Archive

저는 FreeBSD 시스템을 사용하고 있기 때문에 아직 테스트해 보지 않았습니다.

답변3

문제는 오류 메시지를 표시하고 싶지 않거나 .xml 없이 명령을 실행하고 싶지 않다는 것입니다.

첫 번째 경우에는 출력이 리디렉션 2>/dev/null되고 오류 메시지가 표시되지 않습니다.

두 번째 경우에는 실행

for i in $(find ./*.xml '!' -type d | fgrep -v deposit.xml);do mv $i ./Archive;done

답변4

find . ! -name "deposit.xml" -name "*.xml" -exec mv {} ./temp \;

find에는 결과 파일을 피연산자로 사용하여 명령을 실행하고 '! -name' 옵션을 사용하여 파일을 제외할 수 있는 -exec 옵션이 있습니다.

관련 정보