Özel ilk karakterlerle dosya adlarıyla başa çıkma (ör. ♫)


30

Geçenlerde adı '♫' karakteriyle başlayan bir dosyaya rastladım. Bu dosyayı kopyalamak, beslemek ffmpegve terminalde başka şekillerde referans vermek istedim . Genelde garip dosya adlarını otomatik olarak tamamlarım ancak ilk harfi bile yazamadığım için bu başarısız.

Kopyala-yapıştır manevrası yapmak için fareye geçmek istemiyorum. Olası senaryolar için bir sürü kodu ezberlemek istemiyorum. Geçici çözümüm, söz konusu karakteri değiştirmek vim, yapıştırmak !lsve kopyalamak, sonra da bırakmak ve terminale yapıştırmaktı. Bu çalıştı ama oldukça korkunç.

Bu tür senaryolarla baş etmenin daha kolay bir yolu var mı?

NOT: Bir şeyleri değiştirirse, balık kabuğunu kullanıyorum.


7
Onunla çalışmak üzere bir regex oluşturmak için dosyanın diğer bölümlerini kullanabilir misiniz? *restoffile.aviya da böyle bir şey?
slm

1
Bu durumda, kalan isim Kanji ve Katakana'nın (japonca senaryo) bir karışımıydı;
ZirconCode

3
Anladım, sadece soracağımı düşündüm. O zaman Jimmij'in cevabı çözdü mü? Ayrıca rahatsız edici dosyaların ekran görüntüsünü yapıştırmayı düşünür müsünüz? Bunu daha sonra okuyabilecek başkalarına da yardımcı olabilir.
slm

1
Şu an çalışmasını sağlamaya çalışıyorum. Bir senaryoyu nasıl yayınlayacağımı bilmiyorum ama aşağıdaki komutları çalıştırmak size sahte sorunumu verecek:touch '♫ 漢字カ' touch '♫ 漢字タ'
ZirconCode

1
Zsh ile sekmenin size uygun dosyayı seçebileceğiniz bir menü vermesi için seçenekleri kullanabilirsiniz.
Kevin,

Yanıtlar:


35

Dosya adının ilk karakteri yazdırılabilir, ancak ne alfanümerik ne de beyaz boşluk ise [[:punct:]]glob operatörünü kullanabilirsiniz :

$ ls *.txt
f1.txt  f2.txt  ♫abc.txt
$ ls [[:punct:]]*.txt
♫abc.txt

Hmm Bu glob operatörleri hakkında hiçbir şey bilmiyordum, onları okudum ve biraz öğrendim (teşekkür ederim), bu benim direncimde tek bir garip dosya olan problemi çözdü. dosyalar, yeni bir soru sormalı mıyım yoksa bunu güncellemeli miyim?
ZirconCode

Cevabınızı kabul ettim, zamanım olduğunda ikinci senaryoyu yarın göndereceğim. Yardım için teşekkürler.
ZirconCode

6

ls [^a-zA-Z0-9]*Aklıma gelen en basit şey benim için hiledir, fakat terdon'un cevabı extglob kabuğuna veya hatta kabuğundan bağımsız bir yaklaşıma dikkat çekmek için daha iyidir.


Bu, yeterince iyi bir bıçak. Yapabilirsin ls [^[:alnum:]]*aynı şey için. Ama buna karakter sınıfını kullanmak daha iyidir olduğu oldukça sınıfı (es) den, değil ; bu nedenle ls [[:punct:]]*bu dosyayı listeler.
Zengin

6

ls'de, --quote-name, --escape, --literal gibi) yazdırılamayan karakterlerle uğraşmak için bazı anahtarlar vardır (ancak --quote-name, --escape, --literal); ), bu yüzden bu anahtarların hiçbiri yardımcı görünüyor.

Bu nedenle, adlarında herhangi bir karakter içeren dosyalardan kurtulmak için genel bir "kaba kuvvet" yaklaşımı olarak, şunları yapabilirsiniz:

$ /bin/ls -1A|cat -n  # list all files (except . and ..), 1 per line, add line numbers
     1  ♫
     2  f1.txt
     3  f2.txt

Sorunlu dosyayı içeren satırı bulun. Oldukça büyük olasılıkla o 1. sıra olacak, ama diyelim ki 5.. Baskı satırı 5 ve altıgen kodlar:

$ /bin/ls -1A|sed -n 5p|xxd -g 1
0000000: e2 99 ab 0a                                      ....

0a (newline) karakterini yok sayarak, bir kaçış dizesi oluşturun ve çıkışları çevirmek için -e echo seçeneğini kullanın:

$ echo -e '\xe2\x99\xab'
♫

Şimdi bu şekilde kopyalayabilir / taşıyabilir / silebilirsiniz:

$ cp -vi $(echo -e '\xe2\x99\xab') better_name
‘♫’ -> ‘better_name’

Ayrıca, kabuk betiğini kullanmakla sınırlı değilseniz, Python'da şöyle yapabilirsiniz:

$ python
>>> import os
>>> os.listdir('.')
[ ..., '\xe2\x99\xab', ... ]
>>> print '\xe2\x99\xab'
♫
>>> import shutil
>>> shutil.copy('\xe2\x99\xab', 'better_name')

Bu yaklaşımı kullanarak birçok dosyayı işleyebilir, doğru dosyaları seçmek için mantığı yazmanız ve bunları gizlice koymadan yeniden adlandırmanız yeterlidir.

for f in os.listdir('.'):
  if not f.isalnum():
    newname = generate_newname(f)
    if not os.path.exists(newname):
      shutil.copy(f, newname)
    else:
      print newname, 'already exists!'

5

Benzer bir yaklaşım "normal" karakterlerle başlamayan tüm dosyaları listelemek olacaktır. Bash ile bunu yapabilirsiniz

$ shopt -s extglob
$ ls !([[:alpha:]]*)

Ancak, bunun için uygun görünmüyor fish, findonun yerine kullanabilirsiniz :

$ find . -type f -not -name '[[:alpha:]]*'

4

Sembolleri yeniden adlandır

Dosya adlarını özel karakterlerle işlemek için bir yaklaşım - ilk karakter olarak veya dosya adının başka bir yerinde daha basit adlarla yeniden adlandırma yapmaktır .

Orijinal dosya adlarını saklamanız gerekse bile bu kullanılabilir : Dosya adlarının bir kopyasını yeniden adlandırın.
Bu, dosyaları kopyalayarak da yapılabilir, ayrıca dosyalara sembolik bağlantılar veya sabit bağlantılar oluşturarak bunları yeniden adlandırabilirsiniz. cpseçeneği olan kopyaların yerine sembolik bağlantılar oluşturur -s( -lsabit bağlantılar için).

İsimleri temizlemek için "detoks" kullanın.

Dosya adlarını temizlemek için yeniden adlandırmak için detoxkullanılabilir; Dosya adlarını, bir detoxrcdosyada tanımlandığı şekilde çeşitli kurallara göre temizlemek için yeniden adlandırır . Varsayılan olarak, UTF8 karakterleri henüz kaldırılmıştır; Seçeneği -s utf_8-onlyile değiştirilir _:

$ touch '♫ 漢字カ' ♫foo
$ ls -1
♫foo
♫ 漢字カ
$ detox -s utf_8-only * 
$ ls -1                
_ ___
_foo


sembolik bağlantılar üzerinde "detoks"

Yukarıda açıklandığı gibi sembolik bağlantılar üzerinde çalışmakla birleştirildiğinde:

$ mkdir orig
$ cd orig 
$ touch '♫ 漢字カ' ♫foo
$ cd ..
$ mkdir clean
$ cd clean 
$ cp -s ../orig/* .
$ ll               
lrwxrwxrwx 1 14 Oct  8 05:52 ♫foo -> ../orig/♫foo
lrwxrwxrwx 1 21 Oct  8 05:52 ♫\ 漢字カ -> ../orig/♫\ 漢字カ
$ ls -1
♫foo
♫ 漢字カ
$ detox --special -s utf_8-only *
$ ll                                
lrwxrwxrwx 1 21 Oct  8 05:52 _\ ___ -> ../orig/♫\ 漢字カ
lrwxrwxrwx 1 14 Oct  8 05:52 _foo -> ../orig/♫foo

2

Ben kullanmıyorum fishama dokümantasyon sen onun onaltılık karakter kodu için önüne Unicode karakter girmek söylüyor \uya da (16-bit karakter için) \U(32-bit karakterleri için). Bence kod şu 491ebşekilde olabilir:

mv \U000491ebabc.mp3 abc.mp3

yeniden adlandırmak için ♫abc.mp3.

Önde gelen sıfırlara ihtiyacınız olduğunu unutmayın, aksi takdirde abcsonunda altıgen rakam ve karakter kodunun bir parçası olarak ele alınacaktır; 32 bit karakter için 8 rakam girmeniz gerekir.


2

Soruyu sorduğunuzda 2014'te durumun böyle olup olmadığını bilmiyorum, ancak şu anki sürümlerinde fish(2019'dan itibaren), Tabok tuşlarını kullanabileceğiniz zsh tarzı bir seçim almak için iki kez basabilirsiniz . görsel olarak dosya adının herhangi bir bölümünü yazmaya gerek kalmadan istediğiniz dosyayı seçin.


2

Balık , braket joker karakterlerini tasarım gereği desteklemez.

function find_special_filename
    find ! -path './.*' -name '[^-.a-zA-Z0-9_]*' $argv
end

Komut karakterlerle başlamayan gizli dizinleri ve görüntüler Dosya adlarında arama yapmaz letters, digits, . _ -(belgelenmesi cf find).

Not: $argv a, özel bir dizi değişken fonksiyonu bağımsız değişkenleri, bu nedenle temel komut herhangi bir ifade alabilir içeren (Balık kabuk) (örneğin, ad ).

find_special_filename -exec mv '{}' misc/ \;

¹ Aslında, balık braket genişleme (dizi değişken genişleme) destekler, ancak Bash bir terminoloji (parametre ve dosya açılımları) kullanır.



0

Bu sorunlu dosya adlarını saklamak isteyip istemediğinizi söylemediniz. Çözümlerden biri, bu komut dosyasını çalıştırarak yazabileceğiniz adlara (bazılarını veya tümünü) yeniden adlandırarak sorunu bir kez ve herkes için "düzeltmek" olabilir:

#!/bin/sh
for old in *
do
      printf "%s ...? " "$old"
      if read new  &&  [ "$new" != "" ]
      then
             mv -i "$old" "$new"
      fi
done

Bu, her biri tarafından takip edilen mevcut dosya adlarını listeler ...?. Sadece Enterbir dosyayı olduğu gibi bırakmak için yazın; veya yeniden adlandırmak için yeni bir ad yazın. -iSeçenek başka bir mevcut dosyanın adını belirtirseniz üzerine yazma onaylamanızı ister neden olacaktır.

Bu komut dosyası birkaç yolla değiştirilebilir:

  • Joker karakterini ( *) daha kısıtlayıcı bir şeyle değiştirebilirsiniz; örneğin, *.avi *.movher dosyaya bakmak zorunda kalmazsınız.
  • Sen değişebilir mviçin cponun şimdiki adıyla dosyanın bir kopyasını tutmak, böylece ve bir oluşturmak (geçici?) Bir tipleme adıyla kopyalayın.
  • Mevcut dosya adını temel alan yeni bir dosya adı oluşturabilirsiniz. Örneğin,

    if read pfx  &&  [ "$pfx" != "" ]
    then
            mv -i "$old" "$pfx$old"
    fi
    

    Eski adın önüne bir önek tokatlamak sağlar. Benzersiz bir önek seçtiyseniz, otomatik tamamlama kullanmanıza izin verilir.

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.