Bir grup dosya için uzantıyı nasıl yeniden adlandırabilirim?


480

Bir dizinde, bir demet var *.html dosya var. Hepsini yeniden adlandırmak istiyorum*.txt

Bunu nasıl yapabilirim? Ben bash kabuğunu kullanıyorum.

Yanıtlar:


382

Daha iyi bir çözüm için (harici çağrıların aksine sadece bash işlevselliğiyle), diğer yanıtlardan birine bakın .


Aşağıdakiler, sistemin renameprograma sahip olmasını gerektirir ve gerektirmez (çoğunlukla bir sistemde olsa da):

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

DÜZENLEME: Yorumlarda belirtildiği gibi, bu, uygun tırnak (şimdi yukarıda eklenmiştir) olmadan içindeki boşluklu dosya adları için çalışmaz. Dosya adlarında boşluk olmadığını bildiğiniz kendi dosyalarınız üzerinde çalışırken bu işe yarayacaktır, ancak daha sonra yeniden kullanılabilecek bir şey yazdığınızda, uygun alıntıyı atlamayın.


47
Taban adı olmayan ve tırnak işaretleri içeren bir alternatif: mv "$ {file}" "$ {dosya /%. Html / .txt}" (bkz. Man bash, Ayrıntılar için Parametre Genişletme)
Rodrigo Queiro 21: 57'de

7
Tabii ki, sadece dosyaların hepsi geçerli dizinde ise iyidir, çünkü basename yol adı kısmını çıkarır. Sadece bir 'dikkat'!
Jonathan Leffler

6
Bu çözüm sadece yavaş olduğu için değil, içindeki boşluklu dosya adları ile çalışmadığı için kötüdür. Her zaman bash komut dosyalarında uygun alıntı yapmalısınız. mv "$ file" "$ (basename" $ ​​file ".html)". txt çok daha iyi olurdu. Ama yine de, mv "$ files" "$ {files% .html} .txt" çok daha iyi.
Balázs Pozsár

8
pencerelerde sadeceren *.a *.b
Muhammed Umer

2
En azından, $()eski backtick sözdizimi yerine POSIX tarafından belirtilenleri kullanın. Okunabilirliği artırır ve ikincisi ile komut yerine tam ters eğik çizgiden kaçınması gereken karakterleriniz olduğunda sözdizimini çok daha az belirsiz hale getirir.
Charles Duffy

669

Bash kullanıyorsanız, sed, basename, yeniden adlandırma, ifade vb. Harici komutlara gerek yoktur.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

12
Dosya uzantısını bilmiyorsanız kullanabilirsiniz "${file%.*}.txt", ancak bu, uzantısız dosyalar için tehlikeli olabilir.
Jess

1
Bu çalışmayı yaşadığım için sorun yaşayan herkese dikkat edin: $Kıvırcık parantezlerin içinde hiçbir dikkat edin !
doug65536

5
Bu yanıtı kalıcı olarak favori / yer imi için bir yol lazım, tam sözdizimini asla hatırlamıyorum ve bunun için googling
yapıyorum

7
@danip Köşeli ayraç içindeki yüzde işareti yapısı karakterleri sonuna kadar ayırır. Karakterleri en başından ayıran bir parantez içi karma yapısı da vardır.

4
Başka bir Stack exchange yanıtı (bulamıyorum!) Bunu önerdi, ama aynı zamanda --"operator" kullanarak : mv - "$ file" "$ {file% .html} .txt" Bu operatör ile başlayan dosya adlarını önler mv tarafından bağımsız değişken olarak ayrıştırılmasından bir '-'.
rcreswick

191
rename 's/\.html$/\.txt/' *.html

tam olarak ne istediğinizi yapar.


Bahsettiğiniz gibi bashta gerçek bir regex kullanabileceğinizi sanmıyorum - hangi kabuğu kullanıyorsunuz?
DaveR

1
Mac terminal kullanıyorum
bmw0128

İşte Ubuntu'daki rename sürümü için adam sayfası: unixhelp.ed.ac.uk/CGI/man-cgi?rename
Amber

rename bazı sistemlerde bir komuttur. Ben işi yapan bir Perl betiği (aslında ilk Deve kitabından) var. Kabaca aynı işi yapan aynı adlı bir GNU programı da var. Mac'imin sistem tarafından sağlanan bir 'rename' komutu yok - veya PATH'ımda (orta derecede kapsamlı) değil.
Jonathan Leffler

Homebrew'da bir yeniden adlandırma formülü var.
16:22 de revprez

112

Bu benim için .txt'den .txt_bak'a OSX üzerinde çalıştı

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

4
Linux'ta da iyi çalışıyor.
Diziet

Bu noktanın yanı sıra, ama size gitmek .txtiçin .txt_baksadece bitiştirmek zorunda _bak;)
corwin.amber

3
Bu özyinelemeli olarak yeniden adlandırmak için güzel
leachryanb

Harika! Benim pratik kullanım durumunda (Ubuntu 16.04 altında), tüm yeniden adlandırma .scssiçin .sass(yerinde dönüşümden sonra ...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke

2
bu +6000 dosyalarıyla çalıştı, yeniden adlandırın "argüman listesi çok uzundu"
Tony Cronin

94

Kullanmak istediğiniz rename:

rename -S .html .txt *.html

Bu tam olarak ne istediğinizi yapar - uzantısını değişecek .htmliçin .txttüm dosyaları eşleme için *.html.

Not: Greg Hewgill, bunun bir bash yerleşik olmadığını doğru bir şekilde işaret ediyor; ve ayrı bir Linux komutudur. Linux'ta bir şeye ihtiyacınız varsa, bu iyi çalışmalıdır; daha çapraz platformda bir şeye ihtiyacınız varsa, diğer cevaplardan birine bakın.


7
Bu iyi bir çözüm olmakla birlikte, renameprogram bashtüm platformlarla ilgili değildir ve tüm platformlarda mevcut değildir. Sadece Linux'ta gördüm.
Greg Hewgill

15
"$ rename .html .txt * .html", "eval" 1 satırında "yakın" sözdizimi hatasıyla sonuçlanır. "
Amber

8
Doğru sözdizimi rename -S .html .text *.htmlnerede -Saçılımı--subst-all
Marek Sebera

8
demlemek install rename
Nick

4
@GregHewgill, HomeBrew ile Mac OS için kullanılabilir
CodeBrauer


15

Ubuntu Kullanıcıları için:

rename 's/\.html$/\.txt/' *.html

Bu özyinelemeli değil, ama Ubuntu 14.04'te benim için çalıştı.
Max Wallace

9

Bu OSX ve Linux üzerinde çalışan bulduğum en şık çözüm ve git ile de iyi çalışıyor!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

ve git ile:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;


8

İşte rename komutunun bir örneği:

rename -n s/\.htm$/\.html/’ *.htm

-N, bunun bir test çalıştırması olduğu ve gerçekte herhangi bir dosyayı değiştirmeyeceği anlamına gelir. -N kaldırılırsa, yeniden adlandırılacak dosyaların bir listesini gösterir. Yukarıdaki durumda, geçerli dizindeki tüm dosyaları .htm dosya uzantısından .html'ye dönüştürür.

Yukarıdaki test çalıştırmasının çıktısı iyi görünüyorsa, son sürümü çalıştırabilirsiniz:

rename -v s/\.htm$/\.html/’ *.htm

-V isteğe bağlıdır, ancak eklemek için iyi bir fikirdir, çünkü aşağıdaki örnek çıktıda gösterildiği gibi yeniden adlandırma komutu tarafından yapılan değişikliklere sahip olacağınız tek kayıttır:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

Ortadaki zor kısım, aşağıda vurgulanan düzenli ifadelere sahip bir Perl ikamesidir:

rename -v s/\.htm$/\.html/’ *.htm

6

Bu soru Bash'ten açıkça bahsediyor, ancak ZSH'niz varsa oldukça basittir:

zmv '(*).*' '$1.txt'

Eğer alırsanız zsh: command not found: zmvsadece çalıştırın:

autoload -U zmv

Ve sonra tekrar deneyin.

ZMV hakkında ipucu için bu orijinal makale sayesinde.


4

Başkasının web sitesi tarandıktan sonra, geniş bir alt dizin ağacında .html uzantısını eksik binlerce dosya buldum.

Zaten bir .html uzantısına sahip dosyalar (çoğunda hiçbiri yoktu) hariç, hepsini tek seferde yeniden adlandırmak için, bu benim için çalıştı:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

OP durumda ben biraz *, sadece * .txt dosyaları, bu şekilde yeniden adlandırmak için değiştirebilirsiniz:

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

Bozuldu (hamam!):

-iname * .txt
- SADECE .txt ile biten dosyaları düşünün

mv -iv "{}. {txt, html}" - Bul dosya adı olarak bir {} ilettiğinde , $ {filename%. *} mv parametrelerini oluşturmak için taban adını herhangi bir uzantı olmadan ayıklar . bash , {txt, html} 'i iki parametre olarak yeniden yazmak için alır, böylece son komut şu şekilde çalışır:mv -iv "filename.txt" "filename.html"

Gereksinim duyulan düzeltme: dosya adlarındaki boşluklarla uğraşmak


4

Komutmmv (saniyede on binlerce) dosyaları çok büyük sayıda çok verimli bu görevi yerine getirecek gibi görünüyor. Örneğin, tüm .xmldosyaları dosyalara yeniden adlandırmak için şunu .htmlkullanın:

mmv ";*.xml" "#1#2.html"

;yolunu maç olacak, *dosya adı eşleşir ve bunlar olarak adlandırılır #1ve #2yedek adına.

execVeya kanallara dayalı yanıtlar çok yavaş veya çok sayıda dosyada başarısız oldu.


3

Bunu dene

rename .html .txt *.html 

kullanımı:

rename [find] [replace_with] [criteria]

3

Partiye biraz geç. Bunu xargs ile yapabilirsiniz:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

Veya tüm dosyalarınız bir klasördeyse

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

3
Hayır . Ayrıştırmals . Bu komut saçma: lsdoğrudan glob kullanmak yerine işe yaramaz bir glob kullanıyor. Bu boşluklar, tırnak işaretleri ve (tırnak eksikliğinden dolayı) glob karakterleri içeren dosya adları ile kırılacaktır.
gniourf_gniourf

FYI, bağlantılı makaleniz, yeni LS 'terminale yazdırılırsa' kabuğun "dosyadan kaçtığını" bildiren güncel bir not içeriyor. Demek istediğin hala iyi bir kural.
Katastic Voyage

3

Bu, aynı anda birden fazla uzantıyı değiştirmenin iyi bir yoludur:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

Not: uzantı boyutunun aynı olmasına dikkat edin (???)


2

Güzel ve basit!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;

2

PERL'i tercih ederseniz, tam olarak burada istediğinizi yapacak kısa bir PERL betiği (aslında PERL'in yaratıcısı Larry Wall tarafından yazılmıştır) vardır: tips.webdesign10.com/files/rename.pl.txt .

Örneğiniz için aşağıdakiler işe yarayacaktır:

rename.pl 's/html/txt/' *.html

2
Bu soru çoktan cevaplandı ve uzun zaman önce kabul edildi ve cevabınızın söylenenden daha fazlasını getirdiği görülmüyor.
ChristopheLec

1
+1, Larry Wall senaryosu olduğu için (Robin Barker tarafından değiştirildi). En son url şu şekildedir
loretoparisi

1

Daha önce önerilene benzer şekilde, ben de bunu yaptım:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

Önce doğruladım

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;

1

Bir satır, döngü yok:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

Misal:

$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt

Mevcut uzantının tam olarak eşleşmesine bağlı olmayan yalnızca bash yöntemini göstermek için +1. Bu, 3 karakter uzunluğunda veya 4 karakter uzunluğunda veya daha fazla olsun, herhangi bir giriş uzantısı için çalışır
Ciprian Tomoiagă

0

Ne yazık ki portatif olarak yapmak önemsiz değil. Muhtemelen biraz ifade büyüsüne ihtiyacınız var.

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

Yankıyı istediğiniz gibi yaptıktan sonra mutlu edin.

Düzenleme: genel olarak daha esnek basenameolmasına rağmen, muhtemelen bu özel durum için biraz daha okunabilir expr.


Bu soru için en iyi cevap olmasa da, bu benim içindi! Ben sadece bir dosya adı, sadece bir dizede bütün bir yol yeniden adlandırmak için bir yol gerekli. Gönderdiğiniz için teşekkürler!
Halka

0

İşte .edgedosyaları yeniden adlandırmak için kullandığım.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

Cazibe gibi çalışır.


0

Ayrıca Bash'te bir işlev yapabilir, ona .bashrcveya bir şeye ekleyebilir ve daha sonra istediğiniz yerde kullanabilirsiniz.

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

Kullanımı:

change-ext css scss

İşlevdeki kodun kaynağı: https://stackoverflow.com/a/1224786/6732111


0

Geçerli dizin ve alt dizinler altındaki tüm dosyalar için başka paketler olmadan dosya uzantılarını yeniden adlandırın (yalnızca kabuk komut dosyasını kullanın):

  1. rename.shŞu dizin altında aşağıdaki kodla bir kabuk komut dosyası oluşturun :

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
  2. Tarafından çalıştırın ./rename.sh .old .new.

    Örneğin. ./rename.sh .html .txt

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.