Klasör adlarım neden böyle çıktı ve bunu bir komut dosyası kullanarak nasıl düzeltebilirim?


15

Bunun başka bir yerde cevabı varsa, sorunumu nasıl arayacağımı bilmiyorum.

Redhat linux HPC sunucusunda bazı simülasyonlar yapıyordum ve çıktıyı kaydetmek için klasör yapısını işlemek için kodum talihsiz bir hataya sahipti. Klasörü oluşturmak için matlab kodum:

folder = [sp.saveLocation, 'run_', sp.run_number, '/'];

sp.run_numbertamsayı nerede ? Bir dizeye dönüştürmeyi unuttum, ancak bazı nedenlerden dolayı mkdir(folder);(matlab'da) hala başarılı oldu. Aslında, simülasyonlar sorunsuz bir şekilde yürütüldü ve veriler eşleşen dizine kaydedildi.

Şimdi, klasör yapısı sorgulandığında / yazdırıldığında aşağıdaki durumları elde ediyorum:

  • Otomatik tamamlama sekmesini denediğimde: run_ run_^A/ run_^B/ run_^C/ run_^D/ run_^E/ run_^F/ run_^G/ run_^H/ run_^I/
  • Ne zaman kullanmak ls: run_ run_? run_? run_? run_? run_? run_? run_? run_? run_? run_?.
  • Ben rsync kullanarak benim mac için aktarırken --progressopsiyon gösterileri: run_\#003/vb ile giriş tamsayı eşleşen numarası (ı varsayalım) sp.run_number10 çalıştırmak üç rakamına yastıklı, bu nedenlerun_\#010/
  • Bulucudaki klasörleri görüntülediğimde run_ run_ run_ run_ run_ run_ run_ run_ run_ run_?
  • Bu soruya bakarak ve şu komutu kullanarak ls | LC_ALL=C sed -n l:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$

Ben yönetemez cdbu temsillerin herhangi birini kullanarak klasörler halinde.

Bu klasörler binlerce var, bu yüzden bunu bir komut dosyası ile düzeltmek gerekir. Bu seçeneklerden hangisi klasörün doğru temsilidir? Bir bash komut dosyası kullanarak düzgün biçimlendirilmiş bir adla yeniden adlandırmak için bu klasörlere programlı olarak nasıl başvurabilirim? Ve merak uğruna, ilk etapta bu nasıl oldu?


4
"Otomatik tamamlamayı sekmeye çalıştığımda: ... Yazmaya çalışırsam ..." Neden yazıp sizin için otomatik tamamlamanın tamamlanmasına izin vermiyorsunuz? Ayrıca ^Atam anlamıyla değildir ^ve ardından A, ancak Ctrl + A (Ctrl + A genellikle kabuk için bir kısa olduğu Ctrl V Ctrl-A kullanılarak bunu yazabilir).
muru

@muru çalışmıyor ... Kadar ileri run_gidiyorum ve bir şeyler yazmak zorunda
Phill

Düzenlemenizi görmeden önce üzgünüm, bu beni cd yoluyla almayı başarıyor
Phill


9
BTW, matlab'daki mkdir'in bunu yapmasının "bazı nedeni" , unix dosya sistemlerindeki bir dosya veya dizin adındaki SADECE geçersiz karakterlerin NUL ve eğik çizgi olmasıdır /. Kontrol karakterleri de dahil olmak üzere diğer tüm karakterler geçerlidir. Sp.run_number 0 olsaydı ne matlab yapardı bilmiyorum (muhtemelen bir hata ile iptal veya üretmek run_, NUL bayt dizin adı dizesini sonlandırmak gibi). Tabii ki, bu, içinde bir NUL baytı olan 16 bit (veya daha yüksek) değerler için de sorunlu olacaktır ve ayrıca sistem çalıştıran matlabın endianitesine göre değişecektir.
cas

Yanıtlar:


26

Dizinleri yeniden adlandırmak için perl renameyardımcı programını (aka prenameveya file-rename) kullanabilirsiniz.

NOT: Bu karıştırılmamalıdır değildir renameden util-linuxveya başka bir versiyonu.

rename -n 's/([[:cntrl:]])/ord($1)/eg' run_*/

ord()Dosya adındaki her bir kontrol karakterini o karakterin sıra numarasıyla değiştirmek için perl işlevini kullanır . örneğin ^A1 ^Bolur, 2 olur vb.

-nSeçenek göstermek için kuru vadede içindir rename ediyorum eğer izin yapmak. -vYeniden adlandırmak için kaldırın (veya ayrıntılı çıktı için değiştirin ).

eİçerisinde modifiye s/LHS/RHS/egişlemi nedenleri Perl kodu olarak RHS (değiştirme) yürütmek için Perl ve $1LHS'nin eşleşmiş verileri (kontrol karakteri).

Eğer dosya adlarında başına sıfır numara istiyorsanız, birleştirmek olabilir ord()ile sprintf(). Örneğin

$ rename -n 's/([[:cntrl:]])/sprintf("%02i",ord($1))/eg' run_*/ | sed -n l
rename(run_\001, run_01)$
rename(run_\002, run_02)$
rename(run_\003, run_03)$
rename(run_\004, run_04)$
rename(run_\005, run_05)$
rename(run_\006, run_06)$
rename(run_\a, run_07)$
rename(run_\b, run_08)$
rename(run_\t, run_09)$

Yukarıdaki örnekler , yalnızca sp.run_number matlab betiğinizde 0..26 aralığındaysa (bu nedenle dizin adlarında kontrol karakterleri oluşturduysa) çalışır.

HERHANGİ BİR 1 baytlık bir karakterle (örn. 0..255'ten) başa çıkmak için şunu kullanırsınız:

rename -n 's/run_(.)/sprintf("run_%03i",ord($1))/e' run_*/

Eğer sp.run_numberolabilir> 255, sen perl kullanmak zorundayız unpack()yerine fonksiyonunu ord(). Matlab'ın bir dizede dönüştürülmemiş int çıktısını tam olarak nasıl bilmiyorum, bu yüzden denemeniz gerekecek. Ayrıntılar perldoc -f unpackiçin bakınız.

örneğin, aşağıdakiler hem 8 bit hem de 16 bit işaretsiz değerleri açacak ve bunları 5 basamak genişliğine sıfırlayacaktır:

 rename -n 's/run_(.*)/sprintf("run_%05i",unpack("SC",$1))/e' run_*/

Detaylar için teşekkürler! Ben -nseçeneği ile test etmeye çalışıyorum , ama bana onun geçersiz bir seçenek söylüyor - sürüm bilgileri bana verir, rename from util-linux 2.23.2bu yüzden aynı işlevi emin değilim
Phill

3
bu yüzden yardımcı programın perl sürümünü belirttim rename. util-linux's renameçok farklı, çok daha az yetenekli ve komut satırı seçenekleri uyumsuz. debian veya benzeri bir şey çalıştırıyorsanız, file-renamepaketi yüklemeyi deneyin . aksi takdirde dağıtımınız için uygun paketi kurun. zaten yüklenmiş olabilir, çalıştırmayı deneyin prenameveya file-renameyerine rename.
cas

Evet, böyle olduğunu düşündüm. Bunlardan birini işe alıp alamayacağımı göreceğim. Bana yardım etmek için zaman ayırdığınız için tekrar teşekkür ederiz!
Phill

11

Ve merak uğruna, ilk etapta bu nasıl oldu?

folder = [sp.saveLocation, 'run_', sp.run_number, '/'];

sp.run_numbertamsayı nerede ? Ben bir dizeye dönüştürmek unuttum, ama nedense çalışıyor mkdir(folder); (matlab'da) hala başarılı oldu.

Yani, mkdir([...])Matlab'da dosya adını bir dize olarak oluşturmak için dizinin üyelerini birleştirir. Ama bunun yerine ona bir sayı verdiniz ve rakamlar bilgisayardaki karakterlerin gerçekte ne olduğudur. Yani, sp.run_numberoldu 1, bu size değeri ile karakter verdi 1ve sonra değerle karakteri 2vs.

Bunlar kontrol karakterleridir, yazdırılabilir sembolleri yoktur ve bunları bir terminale yazdırmanın başka sonuçları olacaktır. Bunun yerine, genellikle farklı kaçış türleri ile temsil edilirler: \001(sekizli), \x01(onaltılık), ^Ahepsi değerli karakter için ortak temsillerdir 1. Sıfır değerine sahip karakter biraz farklıdır, C ve Unix sistem çağrılarında bir dizenin sonunu işaretlemek için kullanılan NUL baytıdır.

31'den yüksek olsaydı, yazdırılabilir karakterleri görmeye başlarsın, 32 boşluktur (çok görünür değil), 33 = !, 34 = "vb.

Yani,

  • run_ run_^A/ run_^B/- Birincisi run_sıfır baytlı olana karşılık gelir, dize orada biter. Diğerleri, kabuğunuzun kontrol kodlarını kullanmayı sevdiğini gösterir ^A. Gösterim, sayısal değere 1 sahip karakterin de girilebileceği gerçeğine işaret eder Ctrl-A, ancak kabuğa bir kontrol karakteri olarak değil, bir gerçek olarak Ctrl-V Ctrl-Abunu en azından Bash'de yorumlaması gerektiğini söylemeniz gerekir.

  • ls: run_ run_? run_?- lsterminalde yazdırılamayan karakterler yazdırmayı sevmiyor, soru işaretleriyle değiştiriyor.

  • rsync: run_\#003/- bu benim için yeni, ama fikir aynı, ters eğik çizgi bir kaçış işaret ediyor ve geri kalanı karakterin sayısal değeri. Bana öyle geliyor ki, buradaki sayı daha yaygın olduğu gibi sekizli \003.

  • komutunu kullanarak ls | LC_ALL=C sed -n l... run_\006$ run_\a$ run_\b$ run_\t$- \a, \bve \tC sırasıyla alarm (çan), backspace ve sekme için kaçar vardır. Sayısal değerleri 7, 8 ve 9'dur, bu yüzden neden geldiklerini açık olmalıdır \006. Bu C çıkışlarını kullanmak, kontrol karakterlerini işaretlemenin başka bir yoludur. Sondaki dolar işaretleri satır sonlarını işaretler.

Gelince cd, varsayarak benim varsayımlar şunlardır sağ, cd run_garip bir sondaki karakteri olmadan tek dizine gitmeli ve cd run_?, soru işareti herhangi bir tek karakteri ile eşleşen bir topak karakter olduğu için bir hata vermeli ve birden eşleşen dosya adları var ama cdsadece birini bekliyor.

Bu seçeneklerden hangisi klasörün doğru temsilidir?

Hepsi bir bakıma ...

Bash'de, özel karakterleri temsil etmek için tırnak işaretleri içinde \000ve \x00içinde kaçar $'...', böylece $'run_\033(sekizli) veya $'run_\x1b'27 karakter değerine sahip dizine karşılık gelir (ESC olur). (Bash'in ondalık sayılarla kaçmayı desteklediğini düşünmüyorum.)

cas'in cevabının bunları yeniden adlandırmak için bir senaryosu var, o yüzden oraya gitmeyeceğim.


GNU ise ls, yazdırılmayan karakterlerin nasıl gösterileceğini kontrol etmek için -b/ --escapeve --quoting-style=veya QUOTING_STYLEortam değişkeni dahil bazı alıntı seçenekleri vardır. Yine de, karakter versiyonları üzerinde sekizli kaçışları tercih etmenin bir seçeneği olduğunu düşünmüyorum.
Toby Speight

3

En kolayı, yanlış adın oluştuğu aynı ortamda yanlış dosya adı ve doğru dosya adı oluşturmak ve ardından klasörleri doğru adlara taşımak / yeniden adlandırmak olacaktır.

Mevcut adlar arasındaki çarpışmaları önlemek için başka bir hedef klasör kullanın.

./saveLocationA/wrongname1 -> ./saveLocationB/correctname1
./saveLocationA/wrongname2 -> ./saveLocationB/correctname2
./saveLocationA/wrongname3 -> ./saveLocationB/correctname3

Mümkünse, komut dosyasını düzeltmeyi ve tekrar çalıştırmayı tercih ederim; bazı garip böcek post mortem'i düzeltmek muhtemelen daha pahalıya mal olur ve yeni problemler getirebilir.

İyi şanslar!

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.