Soru Bash ile dosyaları yeniden adlandırma


Bash, sürüm numaralarını kaldırmak için bir dizi paketi nasıl yeniden adlandırabilir? Her ikisiyle de oynuyordum. expr ve %%, boşuna.

Örnekler:

Xft2-2.1.13.pkg olur Xft2.pkg

jasper-1.900.1.pkg olur jasper.pkg

xorg-libXrandr-1.2.3.pkg olur xorg-libXrandr.pkg


76
2018-03-02 15:20


Menşei


Bunu düzenli olarak, bir kerelik kullanımlı bir lot betiği olarak kullanmayı düşünüyorum. Kullanacağım herhangi bir sistem üzerinde bash olacak, bu yüzden oldukça kullanışlı olan basitlerden korkmuyorum. - Jeremy L
Daha genel olarak ayrıca bkz. stackoverflow.com/questions/28725333/... - tripleee


Cevaplar:


Bash parametresi genişletme özelliğini kullanabilirsiniz

for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done

Boşluklu dosya isimleri için tırnaklar gereklidir.


149
2018-03-02 15:33



Şimdiye kadarki en iyisini beğendim! - Jeremy L
Ben de hoşuma gitti, ama bash özgü özellikleri kullanır ... Ben normalde onları "standart" sh lehine kullanmayın. - Diego Sevilla
Atışlı tek satırlı interaktif şeyler için her zaman bunu sed-fu yerine kullanırım. Eğer bir senaryo olsaydı, tabiki kaçının. - richq
Yeniden çalıştırma hatalarından kaçınmak için, aynı modeli ".pkg "bölüm, yani" içinde * için * - [0-9.].pkg; mv $ i $ {i / - [0-9.] * .kg / .pkg}; ". Ama hatalar yeterince zararsız (aynı dosyaya taşınıyor). - richq
Bir bash çözümü değil, ama eğer yüklü perl varsa, toplu yeniden adlandırma için kullanışlı yeniden adlandır komutu sağlar rename "s/-[0-9.]*//" *.pkg - Woofas


Tüm dosyalar aynı dizinde ise sıra

ls | 
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' | 
sh

işini yapacaksın sed komut bir dizi oluşturacaktır mv daha sonra kabuğun içine pipetleyebileceğiniz komutlar. Boru hattını iz bırakmadan önce çalıştırmak en iyisidir | sh komutun istediğini yaptığını doğrulamak için.

Birden fazla dizin kullanarak tekrarlamak için

find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh

İçinde şunu unutmayın sed Normal ifade gruplama dizisi, ters eğik çizgiden önce gelen parantezlerdir. \( ve \)tek parantez yerine ( ve ).


27
2018-03-02 15:54



Saflığı bağışla, ama parantezleri ters eğik çizgilerle atlatmak onları gerçek karakter olarak kabul ettirmiyor mu? - devios1
Sed olarak, düzenli ifade gruplama dizisi (tek bir braketten değil). - Diomidis Spinellis
Benim için işe yaramadı, yardım almak için sevinirim .... FROM dosyasının son eki TO dosyasına eklenir: $ find. -type d | sed -n '/(.*)\/(.*) anysoftkeyboard (. *) / mv "\ 1 \ / \ 2anysoftkeyboard \ 3" "\ 1 \ / \ 2effectedkeyboard \ 3" / p' | sh >> >>>>> OUTPUT >>>> mv: rename ./base/src/main/java/com/anysoftkeyboard/base/dictionaries ./base/src/main/java/com/effectedkeyboard/base/dictionaries/dictionaries : Böyle bir dosya ya da dizin yok - Vitali Pom
Köşeli parantez içinde ters eğik çizgi eksik. - Diomidis Spinellis


Böyle bir şey yapacağım:

for file in *.pkg ; do
    mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done

tüm dosyanızın geçerli dizinde olduğunu varsayalım. Değilse, yukarıda Javier tarafından tavsiye edilen bulmayı kullanmayı deneyin.

DÜZENLE: Ayrıca, bu sürüm, yukarıda belirtilenlerin yanı sıra sizi daha fazla taşınabilirliğe yönlendiren bash'a özgü özellikleri kullanmaz.


9
2018-03-02 15:35



Hepsi aynı dizinde. RQ'nun cevabı hakkında ne düşünüyorsun? - Jeremy L
Bash'a özgü özellikleri kullanmamayı, bunun yerine daha standart bir sh kullanmayı tercih ederim. - Diego Sevilla
Bunun bir sonraki nesil çapraz platform, taşınabilir Kurumsal Uygulama ;-) yazmak için değil, çabucak yeniden adlandırmak için olduğunu varsayalım - richq
Haha, yeterince adil ... Sadece benim gibi taşınabilirlik düşünen bir adamın dışında :) - Diego Sevilla
Bu üçüncü örnek için geçerli değildir: xorg-libXrandr (adında kullanılan tire). - Jeremy L


daha iyi kullanım sed Bunun için, bir şey gibi:

find . -type f -name "*.pkg" |
 sed -e 's/((.*)-[0-9.]*\.pkg)/\1 \2.pkg/g' |
 while read nameA nameB; do
    mv $nameA $nameB;
 done

Düzenli ifadeyi bulmak bir egzersiz olarak kalmıştır (boşluk içeren dosya isimleriyle uğraşırken)


3
2018-03-02 15:30



Teşekkürler: Spaces isimlerde kullanılmamaktadır. - Jeremy L


Bu varsayım işe yarıyor gibi görünüyor

  • her şey $ pkg ile biter
  • versiyonunuz her zaman bir "-" ile başlar

.pkg'yi kesip çıkartın, sonra ...

for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done

1
2018-03-02 15:33



Adında tire işareti bulunan bazı paketler var (bkz. Üçüncü örnek). Bu kodunuzu etkiler mi? - Jeremy L
Kullanarak birden çok sed ifadesini çalıştırabilirsiniz. -e. Örneğin. sed -e 's/\.pkg//g' -e 's/-.*//g'. - nojak
Ayrıştırma ls çıktı ve değişkenlerinizi alıntılayın. Ayrıca bakınız shellcheck.net Kabuk betiklerinde yaygın sorunları ve antipatüreleri teşhis etmek için. - tripleee


Çok yaşadım *.txt olarak yeniden adlandırılacak dosyalar .sql aynı klasörde. aşağıda benim için çalıştı:

for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done

1
2017-11-05 17:22



Cevabınızı, OP'nin fiili kullanım durumuyla sınırlandırarak geliştirebilirsiniz. - dakab
Bu, görünür bir sözdizimi hatasının yanı sıra birden çok soruna da sahiptir. Görmek shellcheck.net başlangıç ​​için. - tripleee


İşte bir POSIX yakın eşdeğer şu anda kabul edilen cevap. Bu, yalnızca Bash'i işlemektedir ${variable/substring/replacement} Bourne uyumlu bir kabukta mevcut olan bir parametre genişletme.

for i in ./*.pkg; do
    mv "$i" "${i%-[0-9.]*.pkg}.pkg"
done

Parametre genişleme ${variable%pattern} değerini üretir variable eşleşen herhangi bir sonek ile pattern çıkarıldı. (Ayrıca birde şu var ${variable#pattern} öneki kaldırmak için.)

Alt pateni tuttum -[0-9.]* kabul edilen cevaptan belki de yanıltıcıdır. Normal bir ifade değil, bir glob modeli; Yani "sıfır veya daha fazla sayı veya nokta ile izleyen bir çizgi" anlamına gelmez. Bunun yerine, "bir çizgi, ardından bir sayı ya da bir nokta, onu takip eden bir şey" anlamına gelir. "Her şey" en kısa olası eşleşme olacak, en uzun değil. (Bash sunuyor ## ve %% En kısadan ziyade mümkün olan en uzun önek veya soneki kırpmak için.)


1
2018-03-04 19:41





Bu cevaplar için teşekkür ederim. Ayrıca bir çeşit problemim vardı. .Nzb.queued dosyalarını .nzb dosyalarına taşıma. Dosya isimlerinde boşluklar ve diğer kabartılar vardı ve bu benim problemimi çözdü:

find . -type f -name "*.nzb.queued" |
sed -ne "s/^\(\(.*\).nzb.queued\)$/mv -v \"\1\" \"\2.nzb\"/p" |
sh

Diomidis Spinellis'in cevabına dayanır.

Regex, tüm dosya adı için bir grup ve .nzb.queued öncesi bölüm için bir grup oluşturur ve daha sonra bir kabuk taşıma komutu oluşturur. Dizeleri alıntı ile. Bu ayrıca kabuk betiğinde bir döngü oluşturmayı da engeller çünkü bu zaten sed tarafından yapılır.


0
2017-10-30 08:53



Bunun sadece GNU sed için doğru olduğuna dikkat edilmelidir. BSDs sed üzerinde yorum yapmaz -n seçeneği aynı şekilde. - ocodo