Shell komut dosyası kullanarak Linux'ta tüm dosya adlarındaki boşlukları alt çizgi ile nasıl değiştirebilirim?


17

Tüm xml dosya adlarından boşlukları değiştirmesi gereken kabuk komut dosyasını takip etmeyi denedim

for xml_file in $(find $1 -name "* .xml" -type f);
do
 echo "removing spaces from XML file:" $xml_file
 mv "$xml_file" "${xml_file// /_}";
done

Farz edelim, ben adıyla xml dosyası var xy z.xml, o zaman verir:

removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat `/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat `z.xml': No such file or directory

Yanıtlar:


29

Şununla kullan bash:

find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done

findadında boşluk bulunan dosyaları arar. Dosya adları, -print0özel dosya adlarıyla da başa çıkmak için sınırlayıcı olarak bir nullbyte ( ) ile yazdırılır . Sonra readyerleşik nullbyte tarafından sınırlanmış dosya adlarını okur ve sonunda mvboşlukları bir alt çizgi ile değiştirir.

EDIT: Dizinlerdeki boşlukları da kaldırmak istiyorsanız, biraz daha karmaşıktır. Dizinler yeniden adlandırılır ve daha sonra ad findbulur tarafından erişilemez . Bunu dene:

find -name "* *" -print0 | sort -rz | \
  while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

sort -rzBir klasörde en derin dosyalar taşımak için ilk ve klasörün kendisi sonuncu olacak böylece o, dosya sırasını tersine çevirir. Bu nedenle, tüm dosyalar ve klasör yeniden adlandırılmadan önce hiçbir zaman yeniden adlandırılan klasörler yoktur. mvDöngüde komut çok değişti biraz. Hedef adında, yalnızca dosyanın taban adındaki boşlukları kaldırırız, aksi takdirde erişilemez.


Tüm dizinde alt çizgi ile boşlukları değiştirmeye çalışıyorum ama adı değiştirdikten sonra bu dizine erişilemiyor çünkü hata veriyor.
krishna

@krishna Cevabıma bir düzenleme ekledim.
kaos

1
vay @chaos, sadece iki sistemlerde Bu ikisini koştu ve bir cazibe, birkaç dosya ve yaşamayacağım dirs gibi çalıştı ama sadece birkaç var
somethingSomething

MacOS'ta, -name seçeneğinden önce find komutundaki dizini belirtmemiz gerekir find . -name "* *" -print0 | sort -rz | \ while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
Laszlo Pinter

17
  1. kullanma rename

    find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;

    veya ile $1

    find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
  2. kullanma mv

    find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

    veya ile $1

    find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

Nedenini bilmiyorum ama verdiğiniz emir benim için çalışmıyor. Herhangi bir hata ve çıktı göstermiyor.
krishna

@krishna düzeltildi, üzgünüm
AB

1
Yeniden adlandır benim için çalıştı. Yumruk yumru!
Brian Piercy

1

Bu aynı sorunla karşılaştığımda bulduğum bir yöntem:

for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done

SSL sertifikalarımı otomatik olarak güncellemek için bir bash komut dosyası yazıyordum.


1

Kullanım rename:

rename 's/\s/_/g' ./*.xml

Gerek yok find:)


1
izleyen g'yi normal ifadeye ekleyin ve mükemmel bir şekilde çalışır. 's / \ s / _ / g'
jbrahy

İyi ipucu, teşekkürler :)
Jan Werkhoven
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.