이틀간의 연구 끝에 이곳의 전문가들에게 물어볼 수밖에 없었습니다.
집에 있는 첫 번째 데비안 서버에 NFS 공유를 설정했습니다. Windows 11 컴퓨터에서 일부 파일을 복사했는데 이제 모든 분음 부호가 엉망이 되었습니다. 이제 영향을 받은 모든 파일을 검색하고 잘못된 문자를 올바른 문자로 바꾸는 방법을 찾고 있습니다.
자세한 내용은 다음과 같습니다.
SSH를 통해 시스템에 액세스하면 로케일이 다음과 같이 표시됩니다.
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
파일은 다음과 같습니다.
-rwxrwx--- 1 someuser somegroup 309424046 Jul 5 2018 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV.mkv'
-rwxrwx--- 1 someuser somegroup 1149 Jun 5 2021 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV.nfo'
-rwxrwx--- 1 someuser somegroup 14468 Jul 9 2018 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV-thumb.jpg'
-rwxrwx--- 1 someuser somegroup 328043411 Jul 5 2018 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV.mkv'
-rwxrwx--- 1 someuser somegroup 1506 Jun 5 2021 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV.nfo'
-rwxrwx--- 1 someuser somegroup 17538 Jul 9 2018 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV-thumb.jpg'
-rwxrwx--- 1 someuser somegroup 703251173 Jul 5 2018 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV.mkv'
-rwxrwx--- 1 someuser somegroup 3089 Jun 5 2021 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV.nfo'
-rwxrwx--- 1 someuser somegroup 10441 Jul 9 2018 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV-thumb.jpg'
디렉터리 중 하나에 직접 있으면 다음 명령이 예상대로 작동합니다.
for x in *$'\374'*; do echo "$x" "${x//$'\374'/ü}"; done
문제는 전체 디렉터리 트리에서 영향을 받는 모든 파일과 디렉터리에 대해 이 작업을 수행할 수 있는 방법이 있는지, 그리고 모든 특수 문자에 대해 동시에 수행할 수 있는지 여부입니다. 아니면 이 사건을 해결하는 방법을 더 잘 아는 사람이 있나요?
저는 추가 도구가 설치되지 않은 시스템에서 작업하는 방법을 배우고 싶기 때문에 표준 도구 세트가 포함된 솔루션을 선호합니다.
답변1
사용해 보세요진주 rename
8진수 문자 인코딩을 올바른 유니코드(또는 다른 문자)로 쉽게 바꿀 수 있는 명령입니다. 더 좋은 점은 Perl에는 latin1(및 기타 문자 집합)과 유니코드를 음역할 수 있는 강력한 유니코드 기능이 있다는 것입니다.
참고: Perl 은 , , 또는 rename
라고도 합니다 . 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 유틸리티와 혼동 하지 마십시오. Perl을 사용하면 임의로 복잡한 Perl 코드를 사용하여 파일 이름을 바꿀 수 있지만 파일 이름에 대해 간단하고 유사한 작업을 수행하는 데 가장 일반적으로 사용됩니다 .file-rename
perl-rename
prename
rename
util-linux
rename
sed
s/search/replace/
rename
데비안에서는 패키지에 있습니다 .
다음 줄은 Perl rename
과유니코드::Map8모듈( debian 에 패키지됨 libunicode-map8-perl
)은 이러한 latin1 인코딩 문자의 이름을 해당하는 유니코드 utf-8 문자로 바꿉니다.
요청한 ü 및 ä 움라우트뿐만 아니라 ß eszett... 및 올바른 utf8 형식에 매핑될 수 있는 기타 문자도 수정합니다.
주의해서 사용하세요. 제가 잘하는 유일한 언어는 영어입니다. 제가 고등학교에서 배운 독일어 코스는 약 40년 전이었고, 대학 언어학과 힌디어 코스는 약 30년 전이었습니다. 이것은 AFAICT에서 작동하지만 전문가와는 거리가 멀습니다.
$ rename -n 'BEGIN {
use Unicode::Map8;
our $l1_map = Unicode::Map8->new("latin1")
};
our $l1_map;
$_ = $l1_map->tou($_)->utf8' Star\ Trek\ *
rename(Star Trek - Deep Space Nine - S07E23 - Extreme Manahmen - SDTV.mkv, Star Trek - Deep Space Nine - S07E23 - Extreme Maßnahmen - SDTV.mkv)
rename(Star Trek - Deep Space Nine - S07E23 - Extreme Manahmen - SDTV.nfo, Star Trek - Deep Space Nine - S07E23 - Extreme Maßnahmen - SDTV.nfo)
rename(Star Trek - Deep Space Nine - S07E23 - Extreme Manahmen - SDTV-thumb.jpg, Star Trek - Deep Space Nine - S07E23 - Extreme Maßnahmen - SDTV-thumb.jpg)
rename(Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurcklsst - SDTV.mkv, Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurücklässt - SDTV.mkv)
rename(Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurcklsst - SDTV.nfo, Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurücklässt - SDTV.nfo)
rename(Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurcklsst - SDTV-thumb.jpg, Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zurücklässt - SDTV-thumb.jpg)
이 -n
옵션을 사용하면 시험적으로 실행되므로 실제로 파일 이름을 바꾸지 않고 수행할 작업만 표시됩니다. 요구사항을 충족하는 것으로 확인되면 삭제 -n
하거나 로 대체하여 자세한 출력을 얻으세요.-v
하위 디렉토리 트리와 함께 재귀적으로 사용하려면 다음과 같이 결합하십시오 find
.
find /path/to/directory -type f -print0 |
rename -n -0 '
BEGIN {
use Unicode::Map8;
our $l1_map = Unicode::Map8->new("latin1")
};
our $l1_map;
$_ = $l1_map->tou($_)->utf8'
그런데 테스트 목적으로 ls -l
디렉터리 목록을 스크립트로 변환하여 이름 바꾸기를 위한 더미 파일을 만들었습니다.
touch 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV.mkv'
touch 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV.nfo'
touch 'Star Trek - Deep Space Nine - S07E23 - Extreme Ma'$'\337''nahmen - SDTV-thumb.jpg'
touch 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV.mkv'
touch 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV.nfo'
touch 'Star Trek - Deep Space Nine - S07E24 - In den Wirren des Krieges - SDTV-thumb.jpg'
touch 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV.mkv'
touch 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV.nfo'
touch 'Star Trek - Deep Space Nine - S07E25-E26 - Das, was Du zur'$'\374''ckl'$'\344''sst - SDTV-thumb.jpg'
답변2
답변을 주신 Cas와 Thibault LE PAUL에게 감사드립니다.
@Thibault LE PAUL 이것이 단지 데모 스택 문제인지는 잘 모르겠습니다. NFS를 통해 Windows에서 파일을 복사한 후에는 Windows 탐색기에서도 더 이상 표시되지 않습니다. 발음 구별 부호가 없는 모든 파일이 있습니다. 발음 구별 부호가 있는 모든 파일은 숨겨집니다. 그래서 파일을 다시 복사해서 삼바를 통해 시도해 볼 수도 없습니다.
@cas 내 생각에는 귀하의 솔루션이 잘 작동할 것 같습니다. 마침내 나는 내 자신의 스크립트를 시험해보기로 결정했습니다. 주로 내 시스템에 이름 바꾸기 버전이 설치되어 있지 않고 내가 가지고 있는 버전으로 이 작업을 수행하고 싶었기 때문입니다.
내 해결책은 다음과 같습니다. 두 개의 특수 문자가 직접 인접해 있으면 여전히 오류가 있습니다.
#!/bin/bash
# Variable declaration & initialization
rootDir="/srv/data"
#rootDir="/tmp/test"
echo "Initialized variable rootDir with value $rootDir."
treeDepth=$(find $rootDir -type d | awk -F"/" 'NF > max {max = NF} END {print max}')
echo "Initialized variable treeDepth with value $treeDepth."
dirArray=()
fileArray=()
# Function declaration
grep-invalid-utf8 () {
perl -l -ne '/^([\000-\177]|[\300-\337][\200-\277]|[\340-\357][\200-\277]{2}|[\360-\367][\200-\277]{3}|[\370-\373][\200-\277]{4}|[\374-\375][\200-\277]{5})*$/ or print';
}
echo "Changing directory to $rootDir."
cd $rootDir
echo "Working directory is now $(pwd)."
echo "Looping over directory tree and doing renames as needed."
for ((i=1; i<=$treeDepth; i++)); do
echo "Searching on level $i.";
mapfile -t dirArray < <(find . -mindepth $i -maxdepth $i -type d | grep-invalid-utf8);
for x in "${dirArray[@]}"; do
firstPart="$(dirname "$x")"
lastPart="/$(basename "$x")"
echo "Renaming '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g')' to '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g' | iconv -f WINDOWS-1252 -t UTF-8)'";
eval "$(echo "mv '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g')' '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g' | iconv -f WINDOWS-1252 -t UTF-8)'")";
done
done
echo "Searching for files that need renaming."
mapfile -t fileArray < <(find . -type f | grep-invalid-utf8);
for x in "${fileArray[@]}"; do
firstPart="$(dirname "$x")"
lastPart="/$(basename "$x")"
echo "Renaming '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g')' to '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g' | iconv -f WINDOWS-1252 -t UTF-8)'";
eval "$(echo "mv '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g')' '$firstPart$(echo $lastPart | sed -e 's/'\''/'\''\\'\'\''/g' | iconv -f WINDOWS-1252 -t UTF-8)'")";
done
감사합니다
사샤