Mam kilka katalogów i podkatalogów, które zawierają pliki ze znakami specjalnymi, takie jak ten plik:
robbie@phil:~$ ls test�sktest.txt
test?sktest.txt
Znajdź ujawnia sekwencję ucieczki:
robbie@phil:~$ find test�sktest.txt -ls
424512 4000 -rwxr--r-x 1 robbie robbie 4091743 Jan 26 00:34 test\323sktest.txt
Jedynym powodem, dla którego mogę nawet wpisać ich nazwy w konsoli, jest uzupełnianie tabulatorów. Oznacza to również, że mogę zmienić ich nazwę ręcznie (i usunąć znak specjalny).
Ustawiłem LC_ALL na UTF-8, co wydaje się nie pomagać (również nie w nowej powłoce):
robbie@phil:~$ echo $LC_ALL
en_US.UTF-8
Łączę się z maszyną za pomocą ssh z mojego komputera Mac. Jest to instalacja Ubuntu:
robbie@phil:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"
Shell to Bash, TERM jest ustawiony na kolor xterm.
Pliki te istnieją już od dłuższego czasu i nie zostały utworzone przy użyciu tej instalacji Ubuntu. Nie wiem więc, jakie były kiedyś ustawienia kodowania systemu.
Próbowałem rzeczy w następujący sposób:
find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'
Ale nie mogę znaleźć rozwiązania, które robi wszystko, co chcę:
- Zidentyfikuj wszystkie pliki, których nie można wyświetlić (powyższe ignoruje zdecydowanie za dużo)
- Dla wszystkich tych plików w drzewie katalogów (rekurencyjnie) wykonaj mv stara nazwa nowa nazwa
- Opcjonalnie możliwość transliteracji znaków specjalnych, takich jak ä na a (nie jest wymagane, ale byłoby niesamowite)
LUB
- Prawidłowo wyświetl wszystkie te pliki (i nie ma błędów w aplikacjach podczas próby ich otwarcia)
Mam drobiazgi, takie jak iteracja po wszystkich plikach i przenoszenie ich, ale identyfikowanie plików i prawidłowe formatowanie ich dla polecenia mv wydaje się być trudną częścią.
Wszelkie dodatkowe informacje na temat tego, dlaczego nie wyświetlają się poprawnie lub jak „odgadnąć” prawidłowe kodowanie są również mile widziane. (Próbowałem convmv, ale wydaje się, że nie robi dokładnie tego, czego chcę: http://j3e.de/linux/convmv/ )
Odpowiedzi:
Wydaje mi się, że widzisz ten
�
nieprawidłowy znak, ponieważ nazwa zawiera sekwencję bajtów, która nie jest poprawna UTF-8. Nazwy plików w typowych systemach plików uniksowych (w tym także w twoim) są łańcuchami bajtów i od aplikacji zależy, jakiego kodowania użyć. Obecnie istnieje tendencja do używania UTF-8, ale nie jest to uniwersalne, szczególnie w lokalizacjach, które nigdy nie mogłyby żyć z czystym ASCII i korzystały z innych kodowań, zanim jeszcze istniała UTF-8.Spróbuj
LC_CTYPE=en_US.iso88591 ls
sprawdzić, czy nazwa pliku ma sens w ISO-8859-1 (latin-1). Jeśli nie, wypróbuj inne ustawienia regionalne. Pamiętaj, że tylkoLC_CTYPE
ustawienie regionalne ma tutaj znaczenie.W ustawieniach regionalnych UTF-8 następujące polecenie pokaże wszystkie pliki, których nazwa jest niepoprawna UTF-8:
Możesz sprawdzić, czy mają one większy sens w innym języku za pomocą polecenia recode lub iconv :
Po ustaleniu, że kilka nazw plików jest w pewnym kodowaniu (np. Latin1), jednym ze sposobów ich zmiany jest
Używa komendy perl rename dostępnej w Debianie i Ubuntu. Możesz przekazać go,
-n
aby pokazać, co by to zrobił bez faktycznej zmiany nazw plików.źródło
grep [^[:print:]]
szukać znaków, które nie da się wydrukować. Ale właśnie przetestowałem z GNU grep i nieprawidłowe sekwencje UTF-8 nie zostały złapane[^[:print:]]
(co ma sens, ponieważ nie są to znaki niedrukowalne, w ogóle nie są znakami). Edytowałem swój post, używając dłuższego sposobu grepowania linii z nieprawidłowymi sekwencjami utf8. Zauważ, że poprawiłem także kierunekrecode
iiconv
przykładów.Wiem, że to stare pytanie, ale całą noc szukałem podobnego rozwiązania. Znalazłem kilka pomocnych wskazówek, ale nie zrobiły dokładnie tego, czego potrzebowałem, więc musiałem wymieszać i dopasować kilka, aby uzyskać poprawny wynik, którego szukałem
aby po prostu usunąć znaki specjalne i zastąpić je kropką (.)
aby użyć w cronjob robiłem co następuje, aby uruchomić co minutę
Mam nadzieję, że ktoś uzna to za pomocne, ponieważ sprawiło, że mój dzień :)
źródło
`…`
na$(…)
- zobacz to , to i to . (2) Zawsze powinieneś cytować odniesienia do zmiennych powłoki (np."$f"
), Chyba że masz dobry powód, aby tego nie robić i jesteś pewien, że wiesz, co robisz. Dotyczy to nawetecho "$f" | sed …
. Dotyczy to również całego$(…)
(lub`…`
) wyrażenia; tjmv "$f" "$(echo "$f" | sed "…")"
. … (Ciąg dalszy)mv
--
"$f" …
-
Teraz, gdy wiesz, jakie kodowanie jest używane dla nazw plików na odległym końcu („latin1” - zgodnie z komentarzami do pierwszej odpowiedzi), możesz również postępować w drugą stronę - uruchomić lokalny terminal i ssh w takim sposób, w jaki zdalne nazwy plików są wyświetlane poprawnie (a nie pierwszy sposób: zmień ich nazwy) .
Tak jak ja , możesz uruchomić terminal lokalnie, który działałby w tym specjalnym kodowaniu, być może tak:
LC_ALL = en_US.latin1 xvt &
xvt
oznacza twój program terminalowy.Być może istniejące ustawienia narodowe są nazywane
en_US.iso88591
, a nieen_US.latin1
, jak zakładałem.źródło
To nie spełnia wymagań masowych, ale właśnie miałem podobny problem, w którym miałem wiele wersji pliku o podobnych nazwach, które różniły się tylko pojedynczym dziwnym znakiem. Niestety oznaczało to, że nie mogłem zmienić nazwy przestępców za pomocą sztuczki z symbolami wieloznacznymi, której zwykle używam.
W końcu użyłem Filezilli do połączenia się jako klient SFTP, przejrzałem pliki i zmieniłem ich nazwy za pomocą GUI. Filezilla całkiem dobrze radziła sobie z podejrzanymi postaciami.
źródło