dosya adında ASCII olmayan veya yazdırılamayan karakter içeren dosyaları tanımlama


24

Yaklaşık 700.000 dosya içeren 80 GB boyutundaki bir dizinde, dosya adında İngilizce olmayan karakterlere sahip bazı dosya adları vardır. Zahmetli bir şekilde dosya listesinde trol atmanın dışında:

  • Bu dosya adlarını listelemek veya tanımlamak için kolay bir yol mu?
  • Yazdırılabilir İngilizce olmayan karakter karakterleri oluşturmanın bir yolu - yazdırılabilir aralıkta listelenmeyen karakterler man ascii(bu dosyaların tanımlandığını test edebilirim)?

Yanıtlar:


32

"Yabancı" nın "ASCII karakteri değil" anlamına geldiğini varsayarsak, findadlarında yazdırılabilir ASCII karakterleri olmayan tüm dosyaları bulmak için bir kalıpla kullanabilirsiniz :

LC_ALL=C find . -name '*[! -~]*'

(Boşluk listelenen ilk yazdırılabilir karakterdir http://www.asciitable.com/ , ~sonuncusu.)

Bunun için ipucu LC_ALL=Cgerekli (aslında LC_CTYPE=Cve LC_COLLATE=C), aksi takdirde karakter aralığı yanlış yorumlanır. Ayrıca kılavuz sayfasına bakınız glob(7). Yana LC_ALL=Cnedenleri findASCII olarak dizeleri yorumlamak, bu (örneğin multi-byte karakterleri yazdırır πsoru işaretleri gibi). Bunu düzeltmek için bir programa catyönlendirin (örn. ) Veya dosyaya yönlendirin.

Karakter aralıkları belirlemek yerine [:print:]"yazdırılabilir karakterleri" seçmek için de kullanılabilir. C yerel ayarını ayarladığınızdan emin olun veya tamamen (görünüşte) keyfi bir davranış elde edin.

Örnek:

$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/  foo  foo.c  xrestop-0.4/  xrestop-0.4.tar.gz  π
$ find -name '*[! -~]*'       # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./π
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./π
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./π

1
UTF-8 veya ASCII ile uyumlu olmayan yabancı karakter setleri kullanan dosya adlarına sahip olduğunuzu unutmayın. Bu durumlarda, karakter yerine soru işaretleri görebilirsiniz.
Lekensteyn

1
1, ama ben kullanmak LC_ALL=Cyerine LC_COLLATE=Cbu ayarlamadan C'ye ayarlanmış LC_COLLATE çok mantıklı değil olduğu gibi LC_CTYPELC_ALL değişken ortamda olduğunda bile ve yaptığınızdan emin hala çalışıyor.
Stéphane Chazelas

Eğer SPCbir yazdırılabilir , o zaman ne hakkında TABve LFayrıca tipik metin dosyaları bulunan hangi?
Stéphane Chazelas

1
Teşekkürler - Bu, uzun kısa çizgi, kısa kısa çizgi ve tek tırnaklı bir varyant olan altı dosya buldu. Bunların hepsi MS Word'den geliyordu. LC_ALL ve LC_COLLATE arasında listelenen dosyalarda fark yoktur. LC_COLLATE ASCII olmayan karakterleri doğru görüntülerken LC_ALL görüntülendi ??? yerine. Mükemmel cevap!
şüpheli

1
@suspectus Stephane'nin önerisine dayanarak cevabımla güncellendi. İçin LC_COLLATEve LC_CTYPEayrıca bkz find(1)manpage.
Lekensteyn

6

Her dosya adını kullanarak çevirir tr -d '[\200-\377]'ve orijinal adla karşılaştırırsanız, özel karakter içeren dosya adları aynı olmaz.

(Yukarıdaki ASCII’yi yabancı ile demek istemediğinizi varsaymak)


2
Bu da kaldırır [ve ]çoğunda truygulamaları.
Stéphane Chazelas

Evet - [ve ]sistemimde kaldı.
şüpheli

+1 - çözüm tüm (altı) dosya adını ASCII olmayan sembollerle buldu ( [ve ]s'ye ek olarak ). Teşekkürler.
şüpheli

3

Sen kullanabilirsiniz trbir dosya üzerinde herhangi bir yabancı karakter silmek için ve yabancı karakterler içerdiği olmadığını görmek için orijinal dosya ile karşılaştırın.

find . -type f > filenames
while read filename; do
      stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][[:punct:]]')"
      test "$filename" = "$stripped" || printf '%s\n' "$filename"; 
done < filenames

4
bu benim cevabımın güzel bir uzantısı, ama çok basit, dosya adlarında içlerinde yeni satırlar olabilir ve betiğiniz çalışmaz
Timo

1
findÇıktıyı işlemek istiyorsanız , bu cevapta gösterildiği gibi NUL sonlandırılmış çıktı / girdi kullanın .
Lekensteyn

0

Kabul cevap yararlıdır, ancak dosya adları belirtilen kodlama hazır halde alınıp LANG/ LC_CTYPE, sadece yapmak daha iyi:

LC_COLLATE=C find . -name '*[! -~]*'

Karakter sınıfları bundan etkilenir LC_CTYPE, ancak yukarıdaki komut karakter sınıflarını kullanmaz, yalnızca aralıkları kullanır, bu yüzden LC_CTYPEsıra dışı karakterlerin soru işaretleri ile değiştirilmesini önler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.