첫 글자가 특수한 파일 이름 다루기 (예 : ♫)


30

최근에 이름이 '♫'문자로 시작하는 파일을 발견했습니다. 이 파일을 복사하여 ffmpeg에 넣고 터미널에서 다양한 다른 방법으로 참조하고 싶었습니다 . 일반적으로 이상한 파일 이름을 자동 완성하지만 첫 글자를 입력 할 수 없어 실패합니다.

복사-붙여 넣기 조작을 수행하기 위해 마우스로 전환하고 싶지 않습니다. 가능한 시나리오를 위해 많은 코드를 외우고 싶지 않습니다. 내 임시 솔루션은로 전환하여 문제의 문자를 vim붙여 !ls넣고 복사 한 다음 종료하여 터미널에 붙여 넣었습니다. 이것은 효과가 있었지만 상당히 끔찍합니다.

그러한 시나리오를 다루는 더 쉬운 방법이 있습니까?

참고 : 생선 껍질이 바뀌면 껍질을 사용하고 있습니다.


7
파일의 다른 부분을 사용하여 정규식을 작성하여 작업 할 수 있습니까? *restoffile.avi아니면 이런거?
slm

1
이 경우 나머지 이름은 간지와 가타카나 (일본어 대본)가 혼합되어 있으므로 쉽지 않습니다.
ZirconCode

3
알았어 그냥 물어볼 줄 알았어 그러면 jimmij의 답변으로 해결할 수 있습니까? 또한 문제가되는 파일의 스크린 샷을 붙여 넣어 주시겠습니까? 나중에 읽을 수있는 다른 사람들에게 도움이 될 것입니다.
slm

1
지금 작동 시키려고합니다. 화면을 게시하는 방법을 모르지만 다음 명령을 실행하면 모의 문제가 발생합니다.touch '♫ 漢字カ' touch '♫ 漢字タ'
ZirconCode

1
zsh를 사용하면 옵션을 사용하여 탭에서 적절한 파일을 선택할 수있는 메뉴를 제공 할 수 있습니다.
Kevin

답변:


35

파일 이름의 첫 문자가 인쇄 가능하지만 영숫자 나 공백이 아닌 경우 [[:punct:]]glob 연산자를 사용할 수 있습니다 .

$ ls *.txt
f1.txt  f2.txt  ♫abc.txt
$ ls [[:punct:]]*.txt
♫abc.txt

흠 나는이 glob 연산자에 대해 몰랐고, 그것들을 읽고 약간 배웠습니다 (감사합니다), 그것은 내 디렉토리에 하나의 이상한 파일 인 문제를 해결합니다. 이제 나는 많은 수의 파일을 새로 질문하거나 업데이트해야합니까?
ZirconCode

귀하의 답변을 수락했습니다. 시간이 있으면 내일 두 번째 시나리오를 게시하겠습니다. 도와 주셔서 감사합니다.
ZirconCode

6

나에게 일어나는 가장 간단한 방법은 나를 ls [^a-zA-Z0-9]*위해 속임수이지만, terdon의 대답은 extglob shell 옵션이나 심지어 쉘 독립적 접근법에주의를 기울이는 것이 좋습니다.


이것은 충분히 괜찮은 찌름입니다. ls [^[:alnum:]]*같은 것을 할 수 있습니다. 그러나 그것은 문자 클래스를 사용하는 것이 좋습니다 입니다 오히려 클래스 (들)보다, 아니다 ; 따라서이 ls [[:punct:]]*파일이 나열됩니다.
리치

6

ls는 인쇄 할 수없는 문자를 처리하기위한 스위치 (--quote-name, --escape, --literal과 같은)를 가지고 있지만이 경우 문자는 "인쇄 가능"하지만 "입력 가능"하지는 않습니다 (최소한 키보드에서는! )이므로이 스위치들 중 어느 것도 도움이되지 않는 것 같습니다.

따라서 이름에 문자가 포함 된 파일을 제거하는 일반적인 "브 루트 포스"접근 방식으로 다음을 수행 할 수 있습니다.

$ /bin/ls -1A|cat -n  # list all files (except . and ..), 1 per line, add line numbers
     1  ♫
     2  f1.txt
     3  f2.txt

문제가있는 파일이 포함 된 행을 찾으십시오. 아마도 첫 번째 줄이 될지 모르지만 다섯 번째 줄이라고 가정 해 봅시다. 5 행을 인쇄하고 16 진수로 인코딩하십시오.

$ /bin/ls -1A|sed -n 5p|xxd -g 1
0000000: e2 99 ab 0a                                      ....

0a (개행) 문자를 무시하고 이스케이프 문자열을 구성한 다음 echo의 -e 옵션을 사용하여 이스케이프를 변환하십시오.

$ echo -e '\xe2\x99\xab'
♫

이제 다음과 같이 복사 / 이동 / 삭제할 수 있습니다.

$ cp -vi $(echo -e '\xe2\x99\xab') better_name
‘♫’ -> ‘better_name’

또한 쉘 스크립트 사용에 국한되지 않으면 파이썬에서 다음과 같이 할 수 있습니다.

$ python
>>> import os
>>> os.listdir('.')
[ ..., '\xe2\x99\xab', ... ]
>>> print '\xe2\x99\xab'
♫
>>> import shutil
>>> shutil.copy('\xe2\x99\xab', 'better_name')

이 방법을 사용하면 많은 파일을 처리 할 수 ​​있습니다. 올바른 파일을 선택하고 클로버 링없이 파일 이름을 바꾸는 논리 만 작성하면됩니다.

for f in os.listdir('.'):
  if not f.isalnum():
    newname = generate_newname(f)
    if not os.path.exists(newname):
      shutil.copy(f, newname)
    else:
      print newname, 'already exists!'

5

"일반적인"문자로 시작하지 않는 모든 파일을 나열하는 비슷한 방법이 있습니다. bash에서는 다음과 같이 할 수 있습니다

$ shopt -s extglob
$ ls !([[:alpha:]]*)

그러나 사용할 수없는 것 fish같으므로 find대신 사용할 수 있습니다 .

$ find . -type f -not -name '[[:alpha:]]*'

4

심볼릭 링크 이름 바꾸기

파일 이름의 첫 문자 나 다른 위치와 같이 특수 문자로 파일 이름을 처리하는 한 가지 방법은 더 간단한 이름으로 이름바꾸는 것 입니다.

원본 파일 이름유지 해야하는 경우에도 사용할 수 있습니다. 파일 이름의 사본 이름을 바꿉니다.
파일을 복사 할뿐만 아니라 파일에 대한 심볼릭 링크 나 하드 링크 를 만들어 파일 이름을 바꾸면됩니다. cp옵션 -s( -l하드 링크의 경우)을 사용하여 복사본 대신 심볼릭 링크를 만듭니다 .

이름을 정리하려면 "detox"를 사용하십시오.

파일 이름을 정리하기 위해 이름을 바꾸려면 detox사용할 수 있습니다. 파일에 정의 된 다양한 규칙에 따라 파일 이름을 정리하도록 파일 이름을 바꿉니다 detoxrc. 기본적으로 UTF8 문자는 제거되었습니다. 옵션 -s utf_8-only을 사용하면 다음 으로 대체됩니다 _.

$ touch '♫ 漢字カ' ♫foo
$ ls -1
♫foo
♫ 漢字カ
$ detox -s utf_8-only * 
$ ls -1                
_ ___
_foo


심볼릭 링크의 "해독"

위에서 설명한 것처럼 심볼릭 링크 작업과 결합 :

$ mkdir orig
$ cd orig 
$ touch '♫ 漢字カ' ♫foo
$ cd ..
$ mkdir clean
$ cd clean 
$ cp -s ../orig/* .
$ ll               
lrwxrwxrwx 1 14 Oct  8 05:52 ♫foo -> ../orig/♫foo
lrwxrwxrwx 1 21 Oct  8 05:52 ♫\ 漢字カ -> ../orig/♫\ 漢字カ
$ ls -1
♫foo
♫ 漢字カ
$ detox --special -s utf_8-only *
$ ll                                
lrwxrwxrwx 1 21 Oct  8 05:52 _\ ___ -> ../orig/♫\ 漢字カ
lrwxrwxrwx 1 14 Oct  8 05:52 _foo -> ../orig/♫foo

2

내가 사용하지 않는 fish,하지만 문서가 당신이 그것의 진수 문자 코드를 앞에 붙여 유니 코드 문자를 입력 할 수 있다고 말한다 \u또는 (16 비트 문자) \U(32 비트 문자). 에 대한 코드는 입니다 491eb. 그래서 할 수 있습니다.

mv \U000491ebabc.mp3 abc.mp3

이름을 바꿉니다 ♫abc.mp3.

선행 0이 필요합니다. 그렇지 않으면 abc마지막에 16 진 숫자 및 문자 코드의 일부로 처리됩니다. 32 비트 문자의 경우 8 자리를 입력해야합니다.


2

나는 당신이 질문을했을 때 2014 년에 이미 사건이 있었는지 모르겠지만, 현재 버전 fish(2019 년 현재 )에서는 Tab두 번 눌러 화살표 키를 사용하여 zsh 스타일을 선택할 수 있습니다. 파일 이름의 일부를 입력하지 않고도 원하는 파일을 시각적으로 선택하십시오.


2

물고기 는 디자인 상 대괄호 와일드 카드 ¹를 지원하지 않습니다 .

function find_special_filename
    find ! -path './.*' -name '[^-.a-zA-Z0-9_]*' $argv
end

이 명령은 문자로 시작하지 않는 숨겨진 디렉토리 및 디스플레이 파일 이름에 검색하지 않습니다 letters, digits, . _ -(의 문서 CF find).

참고 : 함수 인수를 포함 $argv하는 특수 배열 변수 (Fish shell)이므로 기본 명령은 모든 표현식 (예 : alias )을 받을 수 있습니다 .

find_special_filename -exec mv '{}' misc/ \;

¹ 실제로 Fish는 대괄호 확장 (배열 변수 확장)을 지원하지만 Bash는 다른 용어 (매개 변수 및 파일 이름 확장)를 사용합니다.



0

이러한 문제가있는 파일 이름을 유지할 것인지는 말하지 않았습니다. 한 가지 해결책은이 스크립트를 실행하여 입력 할 수있는 이름으로 파일의 이름을 일부 또는 전부 바꾸어 문제를 한 번에“수정”하는 것입니다.

#!/bin/sh
for old in *
do
      printf "%s ...? " "$old"
      if read new  &&  [ "$new" != "" ]
      then
             mv -i "$old" "$new"
      fi
done

기존 파일 이름이 각각 뒤에 표시됩니다 ...?. Enter파일을 그대로 두려면 입력 하십시오. 이름을 바꾸려면 새 이름을 입력하십시오. 이 -i옵션을 사용하면 다른 기존 파일의 이름을 지정하면 덮어 쓰기를 확인하라는 메시지가 표시됩니다.

이 스크립트는 여러 가지 방법으로 수정할 수 있습니다.

  • 와일드 카드 ( *)를보다 제한적인 것으로 수정할 수 *.avi *.mov있으므로 모든 파일을 볼 필요는 없습니다.
  • 당신은 변경할 수 mvcp당신이 현재의 이름으로 파일의 복사본을 유지할 수 있도록하고, 생성 (임시을?)를 typeable 이름으로 복사합니다.
  • 기존 파일 이름을 기반으로 새 파일 이름을 만들 수 있습니다. 예를 들어

    if read pfx  &&  [ "$pfx" != "" ]
    then
            mv -i "$old" "$pfx$old"
    fi
    

    이전 이름 ​​앞에 접두사를 때릴 수 있습니다. 고유 한 접두사를 선택한 경우 자동 완성을 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.