파이프라인에서 이름에 공백이 있는 파일 사용

파이프라인에서 이름에 공백이 있는 파일 사용

play파일(공백 포함)이 포함된 폴더가 있습니다 damn file. find출력을 사용하고 파이프할 때 tar:

find play/ -name 'damn*' | tar cf archive.tar -T -

완벽하게 작동합니다. 이것이 작동하는 이유는 무엇입니까? 출력에 find문제를 일으킬 수 있는 공백이 포함되어 있습니다 tar. 이 명령을 사용할 때:

tar cf archive.tar $(find play/ -name 'damn*')

Bash는 다음 오류를 표시합니다.

tar: play/damn: Cannot stat: No such file or directory
tar: file: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

혼란스러워요. 첫 번째 예가 작동하는 이유는 무엇입니까?

답변1

두 번째 예에서는 명령 대체의 출력을 토큰화하는 쉘에 의해 개행 문자가 제거됩니다. 개행 문자는 기본적으로 포함되므로 IFS필드 자체의 일부가 아닌 필드 구분 기호로 간주됩니다. 첫 번째 예에서는 입력이 셸이 아닌 파이프에서 나오므로 셸은 토큰화를 수행할 수 없습니다.

큰따옴표로 묶인 명령 대체( "$(find ... )")는 단어 분리가 발생하는 것을 방지하지만 find내부 명령 대체는 거의 항상 발생합니다.나쁜그런 생각은 하지 마세요. 보안을 극대화하려면 Unix 도구의 GNU 버전에 액세스할 수 있는 한 빈 구분 기호 옵션을 사용해야 합니다.

find dir/ -name '...' -print0 | tar cf foo.tar --null --no-recursion -T -

답변2

find play/ -name 'damn*'파일 이름 목록이 한 줄에 하나씩 생성됩니다. play/damn file일치하는 유일한 파일인 경우 echo 'play/damn file'.

체재-T옵션파일 이름은 줄바꿈으로 구분되어야 합니다. 다른 공백은 파일 이름의 일부로 간주됩니다. 이것이 첫 번째 예제가 작동하는 이유입니다.

당신이 사용할 때$(...), 명령의 출력은 다음과 같습니다.공백으로 분할쉘에 의해 처리된 각 단어는 매개변수가 됩니다 tar. 따라서 play/damnfile두 개의 매개변수가 되며 둘 다 기존 파일이 아닙니다.

관련 정보