Diğer cevaplar , bu sorunun iki önemli özelliğinden birini ele aldı: ihtiyaç duyduğunuz yeniden adlandırma işlemini nasıl başarılı bir şekilde gerçekleştireceğiniz. Bu cevabın amacı, komutun içeriğindeki garip "bareword izin verilmiyor" hata mesajının anlamı da dahil olmak üzere komutlarınızın neden çalışmadığını açıklamaktır rename
.
Bu cevabın ilk bölümü rename
Perl ile Per arasındaki ilişki ve onu ilettiğiniz rename
ilk komut satırı argümanını (kod argümanı) nasıl kullandığına ilişkindir. İkinci bölüm, bir bağımsız değişken listesi oluşturmak için kabuğun genişlemeleri - özellikle de globbing - nasıl gerçekleştirdiğiyle ilgilidir. Üçüncü bölüm Perl kodunda "Bareword'a izin verilmiyor" hataları verenlerin ne olduğuyla ilgilidir. Son olarak, dördüncü bölüm, komut girme ve hata alma arasındaki tüm adımların bir özetidir.
1. rename
Size garip hata mesajları verdiğinde, aramanıza "Perl" ekleyin.
Debian ve Ubuntu'da rename
komut, dosya yeniden adlandırma gerçekleştiren bir Perl betiğidir. Daha eski sürümlerde - 14.04 LTS dahil , bu yazıdan hala desteklenmektedir - komuta işaret eden ( dolaylı olarak ) sembolik bir bağlantıydı . Daha yeni sürümlerde, bunun yerine yeni komut işaret edilir. Bu iki Perl yeniden adlandırma komutu çoğunlukla aynı şekilde çalışır ve her ikisine de bu cevabın geri kalanında olduğu gibi atıfta bulunacağım.prename
file-rename
rename
rename
Komutu kullandığınızda, yalnızca başka birinin yazdığı Perl kodunu çalıştırmazsınız. Ayrıca kendi Perl kodunuzu yazıyorsunuz ve rename
çalıştırmayı söylüyorsunuz . Bunun nedeni ilk komut satırı argümanı size iletmek rename
dışında komutu, seçenek argümanlar gibi -n
, fiili Perl koddan oluşur . rename
Komut her ameliyat için bu kodu kullanan yol adlarının Eğer sonraki komut satırı argümanları olarak geçirebilirsiniz. (Herhangi bir yol adı bağımsız değişkeni rename
iletmezseniz , her satırda bir tane olmak üzere standart girişten yol adlarını okur .)
Kod içinde çalıştırılan bir döngü , dolaşır yol adı bir kere. Döngünün her yinelemesinin üstünde, kodunuz çalışmadan önce özel $_
değişkene o anda işlenmekte olan yol adı atanır. Kodunuz değerinin $_
başka bir şeyle değiştirilmesine neden oluyorsa, bu dosya yeni ada sahip olacak şekilde yeniden adlandırılır.
Perl'deki birçok ifade , işlenen$_
olarak kullanmak için başka bir ifade verilmediğinde değişken üzerinde dolaylı olarak çalışır . Örneğin ikame sentezleme ilk geçtiği değişikliği tarafından tutulan dize değişken için , ya da yapraklar değişmeden bu içermiyorsa . Sadece yazarsanız açıkça kullanmadan operatörü , o zaman çalışır . Bu kısa demek .$str =~ s/foo/bar/
foo
$str
bar
foo
s/foo/bar/
=~
$_
s/foo/bar/
$_ =~ s/foo/bar/
Bu geçmesine yaygındır bir s///
ifadeyi için rename
kod argüman (yani ilk komut satırı argümanı) olarak, ancak gerekmez. Döngünün içinde çalışmasını, her değerini incelemek $_
ve (koşullu olarak) değiştirmek için herhangi bir Perl kodunu verebilirsiniz .
Bunun çok güzel ve yararlı sonuçları var , ancak bunların büyük çoğunluğu bu soru ve cevabın kapsamı dışında. Bunu buraya getirmemin ana nedeni - aslında, bu cevabı göndermeye karar vermemizin ana nedeni - çünkü ilk argümanın rename
aslında Perl kodu olduğu, her zaman garip bir hata mesajı aldığınız ve arama yaparak bu konuda bilgi bulmakta sorun yaşıyorsanız, arama dizesine "Perl" ekleyebilir (hatta bazen "rename" yerine "Perl" yazabilirsiniz) ve genellikle bir yanıt bulacaksınız.
2. İle rename *.DAT *.dat
, rename
komut hiç görmedim *.DAT
!
Gibi bir komut rename s/foo/bar/ *.txt
tipik geçmez *.txt
bir komut satırı argümanı olarak rename
program ve bunu istemiyoruz , adı tam anlamıyla bir dosya yoksa *.txt
umarım, değil mi.
rename
yorumlayamaz glob desenleri gibi *.txt
, *.DAT
, *.dat
, x*
, *y
, veya *
yol adı argüman olarak kendisine geçirilen zaman. Bunun yerine, kabuğunuz üzerinde yol adı genişletmesi gerçekleştirir (buna dosya adı genişletmesi de denir ve aynı zamanda globbing de denir). Bu rename
yardımcı program çalıştırmadan önce olur . Kabuk için, potansiyel olarak çok sayıda yol adlarının içine globs genişler ve ayrı komut satırı bağımsız değişken olarak, hepsini geçer rename
. Ubuntu'da, değiştirmedikçe interaktif kabuğunuz Bash'tır , bu yüzden yukarıdaki Bash referans kılavuzuna bağlandım .
Bir glob kalıbının genişletilmemiş tek bir komut satırı argümanı olarak iletilebileceği bir durum vardır: herhangi bir dosyayla rename
eşleşmediğinde. Farklı mermiler bu durumda farklı varsayılan davranışlar sergiler, ancak Bash'ın varsayılan davranışı, küreyi kelimenin tam anlamıyla geçmektir. Ancak, nadiren bunu istiyorsun! Eğer istediyseniz, alıntı yaparak kalıbın genişletilmediğinden emin olmalısınız . Bu, yalnızca komutlara değil, herhangi bir komuta argüman iletmek için de geçerlidir .rename
Alıntılama yalnızca globbing (dosya adı genişletme) için değildir, çünkü kabuğunuzun alıntılanmamış metin üzerinde gerçekleştirdiği diğer genişletmeler ve bazıları için değil, diğerleri için de "
"
tırnak içine alınmış metinler vardır. Genel olarak, boşluklar da dahil olmak üzere kabuk tarafından özel olarak işlenebilecek karakterler içeren bir argümanı geçmek istediğinizde, bunu tercihen '
'
tırnak işaretleri ile vermelisiniz .
Perl kodu s/foo/bar/
, kabuk tarafından özel olarak işlenmiş hiçbir şey içermez, ancak bunu da alıntılamak ve yazmak benim için iyi bir fikir olurdu 's/foo/bar/'
. (Aslında, benim yaptığım tek nedeni değil henüz alıntı anlattı olmasaydı gibi, bazı okuyuculara kafa karıştırıcı olacağını idi.) Nedeni ben Perl kodu çok yaygın olduğu için bu olurdu iyi olduğunu söylemek yok içerirler Bu karakterleri değiştirirsem ve bu kodu değiştirirsem, alıntı yapmanın gerekli olup olmadığını kontrol etmeyi hatırlamayabilirim. Buna karşılık, kabuğun bir küreyi genişletmesini istiyorsanız, alıntı yapılmamalıdır .
3. Perl tercümanı "bareword'a izin verilmez" ile ne demek
Sorunuzda gösterdiğiniz hata mesajları, koştuğunuzda rename *.DAT *.dat
kabuğunuzun *.DAT
bir veya daha fazla dosya adı listesine genişlediğini ve bu dosya adlarının ilki olduğunu ortaya çıkarır b1.DAT
. Takip eden tüm argümanlar - her ikisi de bu argümandan sonra --came'den *.DAT
genişletilmiş ve *.dat
--came'den genişletilmiştir , böylece yol adları olarak yorumlanırlardı.
Çünkü aslında neyin koştu gibi bir şey oldu rename b1.DAT ...
, çünkü rename
Perl kodu olarak davranır ilk seçenek olmayan argüman, soru olur: neden yok b1.DAT
sen Perl kodu olarak bunu çalıştırdığınızda bu "bareword izin verilmez" hataları üretmek?
Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).
Bir kabukta, onları otomatik olarak diğer dizelere otomatik olarak dönüştürecek istenmeyen kabuk genişlemelerinden korumak için dizelerimizi alıntılarız (yukarıdaki bölüme bakın). Kabuklar, genel amaçlı dillerden çok farklı çalışan özel amaçlı programlama dilleridir (ve çok tuhaf sözdizimleri ve anlambilimleri bunu yansıtır). Ancak Perl, genel amaçlı bir programlama dilidir ve çoğu genel amaçlı programlama dili gibi Perl'de alıntı yapmanın temel amacı, dizeleri korumak değil , onlardan bahsetmektir. Bu aslında çoğu programlama dilinin doğal dile benzemesinin bir yoludur. İngilizceniz varsa ve bir köpeğiniz olduğunu varsayarsak, "köpeğiniz" iki kelimelik bir kelime iken köpeğiniz bir köpektir. Benzer şekilde, Perl'de, '$foo'
bir dize, $foo
adı olan bir şeydir $foo
.
Ancak, hemen her diğer genel amaçlı programlama dili aksine Perl olacak da bazen tırnaksız metni yorumlamak söz o aynı karakterlerden oluşmaktadır anlamında, o kadar "aynı" olan bir dize - bir dize aynı sipariş. Kodu sadece bir bareword ise (hayır $
veya başka bir sigil varsa , aşağıya bakın) ve bunu vermek için başka bir anlam bulamadığında yorumlamaya çalışacaktır . Daha sonra kısıtlamaları etkinleştirerek söylemediğiniz sürece onu bir dize olarak alacaktır .
Perl'deki değişkenler tipik olarak değişkenin geniş türünü belirten sigil adı verilen noktalama işaretiyle başlar . Örneğin, $
anlamına gelir skaler , @
araçlar dizisi ve %
araçlar karma . ( Başkaları da var. ) Eğer kafa karıştırıcı (veya sıkıcı) fark ederseniz Do not endişe, Tek söylemek o kadar getiriyorum çünkü bir geçerli bir ad , bir Perl programda görünür ama değil bir desen öncesinde, bu ad bir bareword olduğu söylenir .
Barewords çeşitli amaçlara hizmet eder, ancak genellikle programda (veya program tarafından kullanılan bir modülde) tanımlanmış yerleşik bir işlevi veya kullanıcı tanımlı bir alt yordamı belirtir. Perl hiçbir adlandırılan yerleşik işlevleri olan b1
veya DAT
Perl yorumlayıcı kodu gördüğünde bu nedenle, b1.DAT
bu tedavi etmeye çalışır b1
ve DAT
altrutinlerin adları gibi. Bu tür altprogramların tanımlanmadığı varsayılarak bu başarısız olur. Daha sonra, kısıtlamalar etkinleştirilmemişse, bunları dize olarak kabul eder. Aslında olsun veya olmasın rağmen bu çalışacaktır amaçlanan bunun olmasını kimse bilemez. Perl .
operatörü dizeleri birleştirir , bu nedenle b1.DAT
dizeyi değerlendirirb1DAT
. Yani, veya b1.DAT
gibi bir şey yazmak için kötü bir yoldur .'b1' . 'DAT'
"b1" . "DAT"
perl -E 'say b1.DAT'
Kısa Perl betiğini say b1.DAT
çalıştıran Perl yorumlayıcısına ileten komutu yazdırarak bunu kendiniz test edebilirsiniz b1DAT
. (Bu komutta, '
'
tırnak geçmesine kabuk söylemek say b1.DAT
tek komut satırı argümanı olarak, aksi takdirde, uzay neden olur say
ve b1.DAT
gereken ayrı kelimeler olarak ayrıştırılır ve perl
ayrı argümanlar olarak alacak. perl
Gelmez değil Tırnakları görürler olarak kabuk onları kaldırır .)
Ama şimdi, dahause strict;
önce Perl betiğinde yazmayı deneyinsay
. Şimdi aynı hata ile başarısız oluyor rename
:
$ perl -E 'use strict; say b1.DAT'
Bareword "b1" not allowed while "strict subs" in use at -e line 1.
Bareword "DAT" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
Bu use strict;
, Perl tercümanının barewordlara dize olarak davranmasını yasakladığı için oldu . Bu özel özelliği yasaklamak için, sadece subs
kısıtlamayı etkinleştirmek yeterli olacaktır . Bu komut yukarıdakiyle aynı hataları üretir:
perl -E 'use strict "subs"; say b1.DAT'
Ancak genellikle Perl programcıları sadece yazacak use strict;
, bu da subs
kısıtlamayı ve diğer iki taneyi mümkün kılıyor . use strict;
genellikle önerilen bir uygulamadır. Yani rename
komut için yapar sizin kodu. Bu yüzden bu hata mesajını alıyorsunuz.
4. Özetle, olan buydu:
- Kabuğunuz
b1.DAT
, rename
her yol adı bağımsız değişkeni için bir döngüde çalışacak Perl kodu olarak işlem gören ilk komut satırı bağımsız değişkeni olarak geçti .
- Bu anlamlandı
b1
ve operatörle DAT
bağlantı kurdu .
.
b1
ve işaretler DAT
ile öneklenmediği için bareword olarak muamele gördüler.
- Bu iki eyersiz, yerleşik işlevlerin veya herhangi bir kullanıcı tanımlı alt yordamın adı olarak kabul edilirdi, ancak bu adların hiçbirinde bu tür şeyler yoktu.
- "Kesin subs" etkin olmasaydı, dize ifadeleri gibi ele alınır
'b1'
ve 'DAT
"birleştirilirdi". Bu, amaçladığınızdan çok uzak, bu özelliğin genellikle yararlı olmadığını aydınlatan.
- Çünkü "sıkı subs", etkinleştirilmiş
rename
tüm sağlayan kısıtlamaları ( vars
, refs
ve subs
). Bu nedenle, bunun yerine bir hata var.
rename
bu hata nedeniyle çıkın. Bu tür bir hata erken gerçekleştiği için, siz geçmiş olmasanız bile, dosya yeniden adlandırma girişimi yapılmamıştır -n
. Bu, kullanıcıları istemeden dosya adı değişikliklerinden ve hatta bazen gerçek veri kaybından koruyan iyi bir şeydir.
Bu cevabın daha önce yapılan bir taslağında birkaç önemli noktayı ele almama yardımcı olan Zanna'ya teşekkürler . O olmasaydı, bu cevap daha az mantıklı olurdu ve hiç gönderilmeyebilirdi.