özel karakterlere sahip dosyaları toplu olarak yeniden adlandırma (veya doğru görüntüleme)


20

Bu dosya gibi özel karakterler içeren dosyalar içeren dizinler ve alt dizinler bir grup var:

robbie@phil:~$ ls testsktest.txt 
test?sktest.txt

Bul bir kaçış dizisi gösterir:

robbie@phil:~$ find testsktest.txt -ls 
424512 4000 -rwxr--r-x   1 robbie   robbie    4091743 Jan 26 00:34 test\323sktest.txt

Konsolda isimlerini bile yazabilmemin tek nedeni sekme tamamlanması. Bu ayrıca onları manuel olarak yeniden adlandırabileceğim (ve özel karakteri çıkarabileceğim) anlamına gelir.

LC_ALL'i (yeni bir kabukta değil) yardımcı gibi görünmeyen UTF-8'e ayarladım:

robbie@phil:~$ echo $LC_ALL
en_US.UTF-8

Makineye mac bilgisayarımdan ssh kullanarak bağlanıyorum. Bu bir Ubuntu kurulumu:

robbie@phil:~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"

Kabuk Bash, TERM xterm rengine ayarlı.

Bu dosyalar bir süredir orada ve bu Ubuntu yüklemesi kullanılarak oluşturulmadı. Yani sistem kodlama ayarlarının ne olduğunu bilmiyorum.

Ben şeyler boyunca denedim:

find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'

Ama istediğim her şeyi yapan bir çözüm bulamıyorum:

  1. Görüntülenemeyen karakterleri olan tüm dosyaları tanımlayın (yukarıdakiler çok fazla yok sayar)
  2. Bir dizin ağacındaki tüm dosyalar için (özyinelemeli olarak) mv oldname newname komutunu yürütün
  3. İsteğe bağlı olarak, ä gibi özel karakterleri a'ya dönüştürme yeteneği (zorunlu değildir, ancak harika olur)

VEYA

  1. Tüm bu dosyaları doğru şekilde görüntüle (ve açmaya çalışırken uygulamalarda hata yok)

Tüm dosyalar üzerinde yineleme ve taşıma gibi bitleri ve parçaları var, ancak dosyaları tanımlamak ve mv komutu için doğru biçimlendirmek zor kısım gibi görünüyor.

Neden doğru görüntülenmediklerine veya doğru kodlamanın nasıl "tahmin edileceğine" ilişkin ek bilgiler de kabul edilir. (Convmv'i denedim ama tam olarak istediğimi yapmıyor gibi görünüyor: http://j3e.de/linux/convmv/ )


Aşağıdaki tek cevap ilk yolu takip eder (onları bulun ve yeni kodlamanızı yeniden adlandırın), ancak ikinci yol da ilginç olacaktır: şimdi, uzak dosya adları için kullanılan kodlamayı bildiğinizde, bu türdeki uzak ana bilgisayara nasıl ssh dosya adlarının doğru görüntülenmesinin bir yolu (ve adları klavyenizle yazarak yönetilebilir)?
imz - Ivan Zakharyaschev

Yanıtlar:


21

Sanırım bu geçersiz karakteri görüyorsunuz çünkü ad geçerli UTF-8 olmayan bir bayt dizisi içeriyor. Tipik unix dosya sistemlerindeki (sizinkiler dahil) dosya adları bayt dizeleridir ve hangi kodlamanın kullanılacağına karar vermek uygulamalara bağlıdır. Günümüzde UTF-8'i kullanma eğilimi var, ancak özellikle düz ASCII ile yaşayamayacak ve UTF-8'in varlığından bile önce başka kodlamalar kullanan yerel bölgelerde evrensel değil.

LC_CTYPE=en_US.iso88591 lsDosya adının ISO-8859-1'de (latin-1) anlamlı olup olmadığını görmeye çalışın . Başlamazsa, diğer yerel ayarları deneyin. Burada yalnızca LC_CTYPEyerel ayarın önemli olduğunu unutmayın .

UTF-8 yerel ayarında, aşağıdaki komut, adı geçerli UTF-8 olmayan tüm dosyaları gösterir:

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'
}
find | grep-invalid-utf8

Recode veya iconv ile başka bir yerde daha anlamlı olup olmadıklarını kontrol edebilirsiniz :

find | grep-invalid-utf8 | recode latin1..utf8
find | grep-invalid-utf8 | iconv -f latin1 -t utf8

Bir grup dosya adının belirli bir kodlamada (örn. Latin1) olduğunu belirledikten sonra, bunları yeniden adlandırmanın bir yolu

find | grep-invalid-utf8 |
rename 'BEGIN {binmode STDIN, ":encoding(latin1)"; use Encode;}
        $_=encode("utf8", $_)'

Debian ve Ubuntu'da bulunan perl rename komutunu kullanır . -nDosyaları gerçekten yeniden adlandırmadan ne yapacağını göstermek için iletebilirsiniz .


Teşekkürler Bugün daha sonra bunları deneyeceğim! Bu kabul edilen cevap olacak gibi görünüyor :)
RobbieV

Bul | grep '[[: print:]]' komutu tüm dosyaları döndürüyor gibi görünüyor. UTF-8, "normal" karakterlere sahip diğer birçok kodlama ile uyumlu olmamalı mı?
RobbieV

@RobbieV: Yazdım ve grep [^[:print:]]yazdırılamayan karakterler aramak istedim . Ama ben sadece GNU grep ile test ettim ve geçersiz UTF-8 dizileri yakalanmıyor [^[:print:]](yazdırılamayan karakterler olmadıkları için mantıklı değiller). Yazımı, geçersiz utf8 dizileriyle daha uzun bir selamlama yolu ile düzenledim. Ayrıca recodeve iconvörneklerinin yönünü de sabitlediğimi unutmayın .
Gilles 'SO- kötü olmayı bırak'

Mükemmel çalıştı. İconv dışında tüm komutları denedim ve hepsi beklendiği gibi çalışıyor. Saf büyü!
RobbieV

Önerilen latin1 kodlaması bile doğruydu :)
RobbieV

1

Biliyorum bu eski bir soru ama bütün gece benzer bir çözüm arıyordum. Birkaç yararlı ipucu buldum ama tam olarak ihtiyacım olanı yapmadılar, bu yüzden aradığım doğru sonucu elde etmek için birkaçını karıştırıp eşleştirmem gerekti

sadece özel karakterleri kaldırmak ve yerine bir (.) nokta koymak

for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done

bir cronjob kullanmak için her dakika çalıştırmak için aşağıdakileri yaptım

*/1 * * * * cd /path/to/files/ && for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done >/dev/null 2>&1

Umarım birisi günümü yaptığı gibi yararlı bulur :)


(1) Anlaşılır olması için, değişim isteyebilirsiniz `…`için $(…)- bkz bu , bu ve bu . (2) Yapmamak için "$f"iyi bir nedeniniz olmadığı sürece kabuk değişken referanslarınızı (örn.) Her zaman teklif etmelisiniz ve ne yaptığınızı bildiğinizden emin olabilirsiniz. Bu bile için geçerlidir echo "$f" | sed …. Ayrıca tüm $(…)(veya `…`) ifade için de geçerlidir ; yani mv "$f" "$(echo "$f" | sed "…")". … (Devamı)
Scott

(Devamı)… (3) Şunu söylemelisiniz ki , ile başlayan dosya adlarına karşı korumak için . (4) “foo ♥ bar.txt” ve “foo ♠ bar.txt” adında dosyalarınız varsa, bu her ikisini de “foo.bar.txt” olarak yeniden adlandırmaya çalışır ve muhtemelen imha edilecek dosyalar. (5) Bunu neden dakikada bir kez yapmak istesin? mv -- "$f" …-
Scott

Dosyaları otomatik olarak indiren bir torrent komut dosyam var. ve bazen bazı dosyaların yükleyiciyi fırlatan karakterleri vardır. bu yüzden dosyaları özel karakterlerle yeniden adlandırarak cron tüm sorunlarımı düzeltti ve yükleyici işini sorunsuz bir şekilde yapıyor.
Topps70

yani (bu dosya, t - aşağı_yüklendi.uzantı) dönüşür (this.fi.le.tha.t.was.down.loaded.ext)
Topps70

0

Şimdi, uzak uçtaki dosya adları için hangi kodlamanın kullanıldığını bildiğinizde ("latin1" - ilk cevaba yapılan yorumlara göre), ikinci yolu da takip edebilirsiniz - böyle bir terminalde yerel bir termninal ve ssh çalıştırın bu şekilde uzaktan dosya adları (: onları adlandırmak yerine ilk yol yerine) doğru görüntülenir .

Gibi bana , böyle, belki de bu özel kodlamada çalışacağına dair yerel bir terminali başlayabileceğini:

LC_ALL = tr_TR.latin1 xvt &

xvt terminal programınızın kısaltmasıdır.

Belki, mevcut yerel denir en_US.iso88591değil, ve en_US.latin1ben varsayıldığı gibi.


0

Bu toplu gereksinimleri karşılamıyor, ancak benzer bir soruna sahip tek bir garip karakterle farklılık gösteren benzer adlara sahip birden fazla sürümüm olduğu için benzer bir sorun yaşadım. Ne yazık ki bu, genellikle kullandığım joker karakteri kullanarak suçluları yeniden adlandıramayacağım anlamına geliyordu.

Sonunda SFTP istemcisi olarak bağlanmak için Filezilla'yı kullandım, dosyalara göz attım ve GUI'yi kullanarak yeniden adlandırdım. Filezilla tehlikeli karakterleri çok iyi idare etti.

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.