Jak usunąć nieprawidłowe znaki z nazw plików?

47

Mam pliki z takimi nieprawidłowymi znakami

009_-_�%86ndringshåndtering.html

Jest to miejsce, w Æktórym coś poszło nie tak w nazwie pliku.

Czy istnieje sposób, aby po prostu usunąć wszystkie nieprawidłowe znaki?

lub może trbyć jakoś wykorzystany?

echo "009_-_�%86ndringshåndtering.html" | tr ???
Sandra
źródło
5
Znaki prawdopodobnie nie są „nieprawidłowe”, inaczej system plików nie zapisałby ich (chyba że zrobiłeś coś naprawdę paskudnego dla FS). Czy próbowałeś zmienić swoje ustawienia regionalne (np. UTF8), aby poprawnie wyświetlać nazwy?
James O'Gorman

Odpowiedzi:

41

Jednym ze sposobów byłoby zastosowanie sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

fileOczywiście zastąp swoją nazwą pliku. Zastąpi to wszystko, co nie jest literą, cyfrą, kropką, podkreśleniem lub myślnikiem znakiem podkreślenia. Możesz dodawać lub usuwać znaki, aby zachować, jak chcesz, i / lub zmienić znak zastępczy na cokolwiek innego lub nic.

James Sneeringer
źródło
4
Użyłem:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
Louis
1
Poszukaj najlepszego rozwiązania H. Hessa poniżej ... (i mój śmieszny komentarz obok :))
Jan Sila
31

Zakładam, że jesteś na Linux-ie, a pliki zostały utworzone na Windowsie. Linux używa UTF-8 jako kodowania znaków dla nazw plików, podczas gdy Windows używa czegoś innego. Myślę, że to jest przyczyną problemu.

Użyłbym „convmv”. To narzędzie może konwertować nazwy plików z jednego kodowania znaków na inny. W Europie Zachodniej jeden z nich zwykle działa:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Jeśli musisz zainstalować go na Linuksie opartym na Debianie, możesz to zrobić, uruchamiając:

sudo apt-get install convmv

Działa dla mnie za każdym razem i odzyskuje oryginalną nazwę pliku.

Źródło: LeaseWebLabs

mevdschee
źródło
1
wygląda to obiecująco, ale jakiś pomysł, jak powiedzieć, co to jest kodowanie? Mam katalog o nazwie, Save the current file in Word 97-2004 format\sco.workflowktóry został utworzony na moim komputerze Mac (za pośrednictwem pakietu Microsoft Office), a powyższe kodowania nie mają żadnego efektu.
Sridhar Sarnobat,
Warto zauważyć, że domyślnie convmv działa w trybie „testowym”, w którym po prostu wykonuje próbę suchą i informuje, które pliki ma przenieść. Następnie powie Ci, aby uruchomić go ponownie z --notestopcją zmiany nazwy plików.
Kenny Rasschaert
16

Zakładam, że masz na myśli, że chcesz przejść przez system plików i naprawić wszystkie takie pliki?

Oto jak bym to zrobił

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Znalazłoby to wszystkie pliki ze znakami innymi niż ascii i zastąpiłoby je znakami podkreślenia ( _). Zachowaj ostrożność, jeśli plik o nowej nazwie już istnieje, nadpisze go. Skrypt można zmodyfikować w celu sprawdzenia takiego przypadku, ale nie wprowadziłem go w celu uproszczenia.

Patrick
źródło
13

Po odpowiedziach na https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-characters można użyć:

rename 's/[^\x00-\x7F]//g' *

gdzie *pasuje do plików, których nazwę chcesz zmienić. Jeśli chcesz to zrobić w wielu katalogach, możesz zrobić coś takiego:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Możesz użyć argumentu -n, renameaby wykonać próbę i zobaczyć, co by się zmieniło, bez zmiany.

naught101
źródło
Czy istnieje sposób, aby to zmienić, aby zachować obce znaki, takie jak na przykład ü i ä?
Starszy Geek,
Tylko drugi działał dla mnie. Wszystko było w tym samym katalogu, więc nie jestem pewien, jaka jest różnica ..?
Shautieh
1
@Shautieh: -n zatrzymuje działanie. Wyjaśnię odpowiedź.
naught101
zmiana nazwy może być powolna w przypadku wielu plików. Jeśli chcesz to przyspieszyć, wciśnij czek, aby znaleźć. Nie jestem jednak pewien, jak to zrobić.
isaaclw
13

Miałem trochę japońskich plików ze zepsutymi nazwami plików odzyskanych z uszkodzonego pendrive'a i powyższe rozwiązania nie działały dla mnie.

Polecam pakiet detox:

Narzędzie detox zmienia nazwy plików, aby ułatwić ich pracę. Usuwa przestrzenie i inne tego rodzaju niedogodności. Przetłumaczy również lub wyczyści znaki Latin-1 (ISO 8859-1) zakodowane w 8-bitowym ASCII, znaki Unicode zakodowane w UTF-8, a znaki specjalne CGI.

Przykładowe użycie:

detox -r -v /path/to/your/files
-r Przejdź do podkatalogów
-v Wypowiadaj się na temat nazw plików 
-n Może być użyty do suchobiegu (pokaż tylko, co zostanie zmienione)
H. Hess
źródło
2
Powinno to być znacznie wyższe, wzywam wszystkich do przyjrzenia się, detoxzanim w zasadzie wymyślimy koło. Jeśli spojrzysz na stronę podręcznika, zobaczysz, że obejmuje ona wszystkie inne proponowane tutaj rozwiązania ze względu na swoją elastyczność.
emk2203
Ezechiela 25:17 - Błogosławiony, który w imię miłosierdzia i dobrej woli popiera to rozwiązanie, bo tak naprawdę jest stróżem swego brata i poszukiwaczem zaginionych dzieci.
Jan Sila
Nieświadomie ścieżka nie może być „.” w debianie. Jeśli użyjesz „.” nic nie znajduje.
isaaclw
Zastanawiam się, czy to naprawdę działa, wydaje się, że usuwa / zamienia chińskie znaki, np. 的节奏啊Ale te znaki są poprawnymi nazwami plików.
林果 皞
5

Ten skrypt powłoki dezynfekuje katalog rekurencyjnie, aby pliki były przenośne między Linux / Windows a FAT / NTFS / exFAT. Usuwa znaki kontrolne /:*?"<>\|i niektóre zastrzeżone nazwy systemu Windows, takie jak COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

Linux jest mniej restrykcyjny w teorii ( /i \0jest surowo zabroniony w nazwach plików), ale w praktyce kilka znaków koliduje z poleceniami bash (jak *...), więc należy ich unikać w nazwach plików.

Świetne źródła ograniczeń nazewnictwa plików:

KrisWebDev
źródło
1
To, czego szukam! ale dodaj cudzysłowy, aby wesprzeć katalogi ze spacjami znajdź „$ 1” -depth -exec bash -c 'dezynfekuj „0 $” {} \;
mmv-ru
1

Jeśli chcesz obsługiwać osadzone znaki nowej linii, znaki wielobajtowe, spacje, wiodące myślniki, ukośniki odwrotne i spacje, potrzebujesz czegoś bardziej niezawodnego, zapoznaj się z tą odpowiedzią:
https://superuser.com/a/858671/365691

Jeśli ktoś jest zainteresowany, umieszczam skrypt na code.google.com: rnf-bash-rename-script

A.Danischewski
źródło
Link do skryptu tutaj rozwiązał dla mnie problem
Jeremiah Rose
0

Używam tego jednowierszowego do usuwania nieprawidłowych znaków w plikach napisów:

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.-]/./g;s/\.\.\././g;s/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. Przetwarzaj tylko pliki * .srt (* można użyć zamiast * .srt do przetwarzania każdego pliku)
  2. Usuwa wszystkie inne znaki oprócz liter A-Za-z, cyfr 0-9, kropek „.” I myślnika „-”
  3. Usuwa możliwe podwójne lub potrójne okresy
  4. Sprawdza, czy nazwa pliku wymaga zmiany
  5. Jeśli true, zmienia nazwę pliku za pomocą polecenia mv, a następnie wyświetla zmiany dokonane za pomocą polecenia echo

Działa w celu normalizacji nazw katalogów filmów:

for f in */; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' -e 's/\.\.\././g' -e 's/\.\././g' -e 's/\.*$//'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done

Te same kroki co powyżej, ale dodałem jeszcze jedną komendę sed, aby usunąć kropkę na końcu katalogu

X-Men Days of Future Past (2014) [1080p]
Zmodyfikowano do:
X-Men.Days.of.Future.Past.2014.1080p

Brian Kuepper
źródło
-2

dla pliku w *; do mv "$ file" $ (echo "$ file" | sed -e 's / [^ A-Za-z0-9. -] / / g'); gotowy &

Jairo Bernal
źródło
2
Powinieneś wyjaśnić, co robi Twój kod i użyć właściwego formatowania. Twój kod może powodować usunięcie plików poprzez wprowadzenie kolizji w nazwach. A prowadzenie całej sprawy w tle jest trochę głupie.
kasperd