공백이 포함된 목록을 반복하는 방법은 무엇입니까?

공백이 포함된 목록을 반복하는 방법은 무엇입니까?

때때로 공백이 포함된 목록을 반복해야 합니다.

이것이 내가 지금 사용하고 있는 스크립트이다

locate .txt > list

for book in $(cat list)
do
    cp "${book}" /mnt/e/BOOK
done

그런 다음 모든 .txt 파일을 지정된 디렉터리에 복사해야 합니다. 내 목록에 다음이 포함되어 있으면 문제가 없습니다.

/mnt/d/txtfiles/mytextfile1.txt

그러나 스크립트가 반복되면 다음과 같이 나타납니다.

/mnt/d/txtfiles/My text . File2.txt

공백으로 인해 목록 파일 경로가 한 줄에 있는 동안 반복하는 데 문제가 있습니다.

답변1

임의의 파일 이름을 처리하려면 파일 경로에 나타날 수 없는 바이트로 목록을 구분해야 합니다. 작동하는 유일한 것은 바이트 0입니다.

GNU 도구를 가정하면:

locate -0 '*.txt' |
  xargs -r0 cp -it /mnt/e/BOOK

또는 다음을 사용하여 zsh:

cp -i ${(0)"$(locate -0 '*.txt')"} /mnt/e/BOOK/

(그러나 이 방법과 달리 xargs파일 목록이 너무 크면 실패할 수 있으므로 이 경우 여러 호출을 실행하여 문제를 해결할 수 있습니다. 일치하는 파일이 없으면 xargs오류 정보도 얻을 수 있습니다. )cp

0행이 아닌 NUL로 구분된 레코드에서 작동하는 이러한 옵션 또는 매개변수 확장 플래그는 파일 경로 목록을 처리하도록 특별히 설계되었습니다.

텍스트 줄(*nix에서는 제한된 수의 문자(바이트 아님)로 구성된 개행으로 구분된 시퀀스임)는 일반적으로 파일 경로에 저장할 수 없습니다. 왜냐하면 파일 경로가 텍스트임을 보장할 수 없고 줄바꿈이 포함될 수 있기 때문입니다.

Yours 는 $(cat list)목록 컨텍스트에서 인용되지 않은 명령 대체이기 때문에 대부분의 Bourne과 같은 쉘에서 IFS-split+glob을 경험하지만 zsh.

여기 locate에서는 NUL로 구분된 레코드를 포함 locate -0하도록 목록을 변경하고 list, NUL로 분할되도록 IFS 분할을 조정하고 glob활성화되지 않았는지 확인해야 합니다.

그러나 이것은 다른 쉘이 해당 변수에 NUL 저장을 지원하지 않는 경우에만 작동 IFS=$'\0'하지만 위에 표시된 매개변수 확장 플래그(명시적 분할 연산자)를 사용하는 것이 전역적으로 변경하는 것보다 훨씬 낫습니다.zshzsh0IFS

쉘 4.4 이상에서는 bash대안은 다음과 같습니다:

locate -0 '*.txt' > list &&
  readarray -td '' list < list &&
  cp -i "${list[@]}" /mnt/w/book

또는 list파일 중개자 없이:

readarray -td '' list < <(locate -0 '*.txt') &&
  cp -i "${list[@]}" /mnt/w/book

locate .txt또한 이는 경로의 모든 항목을 반환한다는 점에 유의하세요 . 예를 들어 .txt여기에는 가 포함될 수 있습니다 . 해당 경로만 반환됩니다./foo.txting/bar.mp4locate '*.txt'존재하다 .txt. 예를 들어, 파일을 계속 포함하고 싶지만 .txt.gz전체 경로가 아닌 파일 이름만 확인하려면 ..txt.in.txtlocate -0 -b .txt

관련 정보