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 …