파일 이름에서 특이한 문자를 피하려면 "찾기"를 사용하십시오. -printf"%p\n"`

파일 이름에서 특이한 문자를 피하려면 "찾기"를 사용하십시오. -printf"%p\n"`

find명령 의 파일 경로

find . -printf "%p \n"

특이한 문자(공백, 백슬래시, 큰따옴표 등)를 이스케이프 처리하지 마세요.

이 옵션 은 -ls이스케이프된 경로를 인쇄하지만 .ls -dilsprintf

효율적인 명령이 필요하므로 추가 명령을 실행해도 ls도움이 되지 않으며 모든 추가 문자를 인쇄하지도 않습니다.

이스케이프된 경로를 출력하는 다른 (우아한) 방법이 있습니까 find?

답변1

find -exec일반적으로 모든 파일 이름에 대해 실행되는 명령을 사용 하거나 find -print0nul ​​바이트로 구분된 항목을 읽을 수 있는 일부 명령(예: xargs -0)으로 이름을 파이프하려고 합니다.

정말로 인용된 문자열을 원한다면 Bash에는 이를 수행할 수 있는 몇 가지 옵션이 있습니다:

$ find -exec bash -c 'printf "%s\n" "${@@Q}"' sh {} +
'./single'\''quote'
'./space 1'
$'./new\nline'
'./double"quote'

$ find -exec bash -c 'printf "%q\n" "$@"' sh {} +
./single\'quote
./space\ 1
$'./new\nline'
./double\"quote

이를 위해서는 쉘에 대한 추가 호출이 필요하지만 단일 exec로 여러 파일 이름을 처리하는 데 사용할 수 있습니다.


권한 비트(ACL 아님) 저장과 관련하여 다음을 수행할 수 있습니다(GNU find에서):

find -printf "%#m:%p\0" > files-and-modes

그러면 권한, 콜론, 파일 이름 및 nul 바이트가 포함된 항목이 출력됩니다(예: ). 그럴 것이다0644:name with spaces\0아니요무엇이든 이스케이프하고 대신 파일 이름을 있는 그대로 인쇄합니다(단, 터미널로 출력하지 않는 한, 이 경우 최소한 줄 바꿈이 엉망이 됩니다.)

Perl 스크립트를 사용하여 결과를 읽을 수 있습니다.

perl -0 -ne '($m, $f) = split/:/, $_, 2; chmod oct($m), $f; ' < files-and-modes 

또는 Bash에서는 거의 설명을 참조하십시오.

while IFS=: read -r -d '' mode file ; do
    # do something useful
    printf "<%s> <%s>\n" "$mode" "$file"
    chmod "$mode" "$file"
done < files-and-modes

내가 테스트한 바에 따르면 개행, 따옴표, 공백 및 콜론 과 함께 작동합니다 . IFS=" "이름에 뒤에 공백이 포함되어 있으면 설정에 따라 공백이 제거되므로 공백 이외의 다른 것을 구분 기호로 사용해야 합니다 .

답변2

이를 통해 zsh다음을 수행할 수 있습니다.

print -r -- ./**/*(.D:q)

.마찬가지로 will과 같은 숨겨진 파일과 -type f참조 용도 D포함됩니다 ( -style 참조를 사용하면 이것이 기대하는 참조 유형인지 알 수 없습니다).find:qzsh

다양한 스타일의 인용을 얻을 수 있습니다.

$ print -r -- ./**/*(.D:q)
./$'\200' ./a\ b ./é ./\"foo\" ./It\'s\ bad ./$'\n'
$ files=(./**/*(.D))
$ print -r -- ${(q)files}
./$'\200' ./$'\n' ./a\ b ./é ./\"foo\" ./It\'s\ bad
$ print -r -- ${(qq)files}
'./�' './
' './a b' './é' './"foo"' './It'\''s bad'
$ print -r -- ${(qqq)files}
"./�" "./
" "./a b" "./é" "./\"foo\"" "./It's bad"
$ print -r -- ${(qqqq)files}
$'./\200' $'./\n' $'./a b' $'./é' $'./"foo"' $'./It\'s bad'

( 인쇄할 수 없는 \200 바이트에 대해 내 터미널 에뮬레이터가 표시하는 자리 표시자입니다.)

여기에서 복구 가능한 방식으로 권한을 저장하려면 다음을 수행하세요.

find . -type f -printf '%m\0%p\0' > saved-permissions

복원하려면(GNU 가정 xargs):

xargs -r0n2 -a saved-permissions chmod

그러나 이는 chmod파일당 하나의 호출을 실행하므로 매우 비효율적입니다. 다음과 같이 chmod내장 쉘을 사용할 수 있습니다 .zshzmodload zsh/files

zmodload zsh/files
while IFS= read -rd '' mode && IFS= read -rd '' file; do
  chmod $mode $file
done < saved-permissions

답변3

더 간단한 해결책을 찾았습니다.

find -exec echo \'{}\' \;

이를 사용하여 다른 프로그램으로 파이프할 수 있습니다.

find -exec echo \'{}\' \; | xargs ls 

또는 echo 대신 간단히 임의의 명령을 사용하고 인수를 원하는 수만큼 추가할 수 있습니다.

find -exec mv \'{}\' somewhereelse \;

먼저 테스트하는 것을 잊지 마세요 echo.

마지막은 작동하지 않습니다mv는 파일에 액세스하기 전에 따옴표를 제거하지 않으므로 대신 파이프를 사용하십시오.

find -exec echo mv \'{}\' somewhereelse \;| bash

답변4

왜 모든 캐릭터를 탈출하지 않습니까? 그런 다음 모든 작업(ls, rm, echo 등)에서 작동합니다.

find -name *.txt | sed -E 's/(.)/\\\1/g' | xargs ls

-exec( 더 효과적이려면 이것을 형태에 맞게 조정해야 할 수도 있습니다 )

관련 정보