`xargs`는 `find`가 제공한 파일 이름을 어떻게 처리합니까? 이로 인해 문제가 발생할 수 있습니까?

`xargs`는 `find`가 제공한 파일 이름을 어떻게 처리합니까? 이로 인해 문제가 발생할 수 있습니까?

findutils 매뉴얼에서 배웠습니다.xargs

많은 응용 프로그램에서 파일 이름에 특수 문자가 포함되어 있기 때문에 xargs가 파일을 처리할 수 없는 경우 일부 데이터가 손실될 수 있습니다.

그러나 이는 이름을 구분하기 위해 공백을 사용하면 발생할 수 있는 문제의 극단적인 예입니다. cron에서 매일 다음 명령을 실행하면 모든 사용자가 시스템의 모든 파일을 삭제할 수 있습니다.

find / -name ’#*’ -atime +7 -print | xargs rm

예를 들어 다음과 같이 할 수 있습니다.

eg$ echo > ’#
vmunix’

그런 다음 예약된 작업이 있습니다./vmunix를 삭제합니다., /를 현재 디렉토리로 사용하여 xargs를 실행하는 경우.

도착하다다른 파일 삭제, 예를 들어 /u/joeuser/.plan에서 다음을 수행할 수 있습니다.

eg$ mkdir ’#
eg$ cd ’#
eg$ mkdir u u/joeuser u/joeuser/.plan’
eg$ echo > u/joeuser/.plan’
/#foo’
eg$ cd ..
eg$ find . -name ’#*’ -print | xargs echo
./# ./# /u/joeuser/.plan /#foo

위의 예에서 xargs제공된 파일 이름으로 무엇을 하고 find파일을 삭제하는 방법은 무엇입니까?

감사해요.

답변1

문제는 xargs입력을 읽고 명령에 전달하는 방법입니다.

우리는 이것을 쉽게 볼 수 있다rm -i

$ touch a 'b c' 'd
> e'
$ find -type f | cat
./d
e
./b c
./a
$ find -type f | xargs rm -i
rm: cannot remove './d': No such file or directory
rm: cannot remove 'e': No such file or directory
rm: cannot remove './b': No such file or directory
rm: cannot remove 'c': No such file or directory
rm: remove regular empty file './a'? $ 

./a, ./b, c, ./d및 5개의 파일을 삭제하려고 했습니다.e

따라서 파일 이름에 공백과 줄 바꿈이 있으면 두 개의 인수가 명령에 전달됩니다.

표준 솔루션은 다음 find -print0과 같습니다.xargs -0

$ find -type f -print0 | xargs -0 rm -i
rm: cannot remove '.': Is a directory
rm: remove regular empty file './d\ne'? 
rm: remove regular empty file './b c'? 
rm: remove regular empty file './a'? $ 

이제 NUL 문자(파일 이름의 일부가 될 수 없음)가 구분 기호로 사용되며 공백은 중요하지 않습니다.

답변2

문제의 나머지 절반은 대응 방법입니다. 대답은 \0공백 구분 기호 대신 구분 기호를 사용하는 것입니다( -0파일 이름에는 허용되지 않으며 허용되지 않는 유일한 문자입니다. /파일 이름의 일부이지만 특별한 목적이 있습니다).

이렇게 하려면 코드를 다음과 같이 변경하세요.

find … -print0 | xargs -0 …

관련 정보