다음과 같은 이름을 가진 여러 디렉터리가 있습니다.
재귀적으로 끝에서 줄바꿈을 제거하고 싶습니다.
나는 확인했다반복적으로 디렉터리 이름 바꾸기
나도 확인했다파일 이름에서 개행 문자 제거
제안된 솔루션은 다음과 같습니다.
find -name $'*\n*' -exec rename $'s|\n| |g' '{}' \;
하지만 내 경우에는 find -name $'*\n*'
아무것도 반환되지 않습니다. 삭제하면 $
디렉토리를 찾을 수 있습니다
% find . -name '*\n*'
./second?
% find . -name '*\r*'
./third?
./first?
그러나 실행하면 find . -name '*\n*' -exec rename $'s|\n| |g' '{}' \;
디렉토리 이름이 바뀌지 않습니다. 나는 find . -name $'*\n*' -exec rename $'\n' ' ' {} \;
또한파일 이름에서 개행 문자를 반복적으로 제거합니다.. 또한 디렉토리 이름을 바꾸지 않았습니다.
어떡해?
답변1
전에도 그렇게 말했잖아
printf "%q\n" *
프로그램first$'\342\200\251' second$'\342\200\251' third$'\342\200\251'
이것은 $'\342\200\251'
일반적인 개행 문자이지만유니코드 U+2029 단락 구분 기호, UTF-8로 인코딩됩니다. 출력에는 8진수 바이트가 있습니다 e2 80 a9
.
그렇기 때문에 find -name $'*\n*'
일치하지 않습니다. 달러가 없으면 문자만 일치하는 것과 같습니다 -name '*\n*'
. 이러한 모드는 다음 문자를 특별하지 않게 만드는 쉘 전역 모드일 뿐입니다. 예를 들어 별표 하나만 일치하는 반면 모든 항목은 일치합니다. 특별한 건 아니니까 그냥 놔두세요.-name '*n*'
n
second
-name
\
\*
*
n
\n
이제 그것이 무엇인지 알았으므로 개행 문자를 제거한 것처럼 제거할 수 있습니다. Perl 이름 바꾸기를 통해 File::Rename
제거해야 합니다 (예: 다음을 사용).
find . -depth -name $'*\342\200\251' \
-execdir rename -v $'s|\342\200\251||g' '{}' +
-depth
리프가 있는 브랜치 이전에 리프의 이름을 바꿔야 하며 -execdir
(표준은 아니지만 일반적임) rename
이름 바꾸기를 위해 파일의 기본 이름만 사용하여 파일이 포함된 디렉터리에서 리프를 호출해야 합니다.
... rename -v 's|\342\200\251||g'
Perl 표현식이고 Perl이기 때문에 작동해야 합니다.하다백슬래시 해석도 자체적으로 이스케이프됩니다.
가지고 있는 명령이 rename $'s|\n| |g'
공백으로 대체되지만 이름 끝에 문자가 있기 때문에 혼란스럽기도 합니다.
답변2
그리고 zsh
:
autoload zmv # best in ~/.zshrc
zmv -v $'(**/)(*[\n\u2029]*)(#qD)' $'$1${2//[\u2029\n]}'
두 개의 개행 문자(U+000A)를 제거하려면 또는단락 구분 기호문자(U+2029).
또는:
zmv -v $'(**/)(*[[:cntrl:]]*)(#qD)' $'$1${2//[[:cntrl:]]}'
모든 제어 문자를 제거합니다.
그러나 U+2029의 분류 여부는 cntrl
시스템에 따라 다릅니다. Ubuntu 20.04에서는 작동하지만 FreeBSD 12.2에서는 작동하지 않습니다. 실행 [[ $'\u2029' = [[:cntrl:]] ]] && echo yes
하여 시스템을 확인하십시오.