Find komutunu kullanarak (1) dosya adlarından nasıl kaldırılır


13

Son zamanlarda tüm FLAC dosyalarımı Mac OS 10.7'de (Lion) XLD kullanarak 44.1 kHz daha düşük örnekleme hızına ve 24 bitlik bit derinliğine (iPhone / iPod bunun üzerinde hiçbir şey desteklemediğinden) dönüştürdüm.

XLD'ye önceki tüm dosyaların üzerine yazmasını söylememe rağmen, XLD aşağıdaki (1)gibi bir dosyanın sonuna

some_song.m4a

için

some_song(1).m4a

Şimdi (1)bunu dönüştürdüğüm tüm FLAC dosyalarından kaldırmak istiyorum .

Dosyaları yeniden adlandırmak için muhtemelen bir program hatta AppleScript kullanabileceğimi biliyorum, ancak komut satırının eski okul yolunu kullanarak öğrenmek istedim.

Ben find . -name *\(1\).m4atüm dönüştürülmüş FLAC dosyasını kapmak biliyorum .

Sonra bir şey yapmak -execve mvbulunan tüm dosyaları yeniden adlandırmak zorunda biliyorum . Ama anlayamadığım şey orijinal dosya adını nasıl saklayacağımız ve yalnızca (1).

Dosya adının değiştirmek istemediğim kısmını saklamak için belki bazı grup regex yakalama yapmalıyım? Ya da belki her şeyi bir satırda yapmak mümkün değildir ve bir kabuk betiği oluşturmalıyım (ki o kadar rahat değilim, ama denemeye hazırım).

Herhangi bir ipucu veya öneri bekliyoruz! Teşekkürler!


5
Neden inişli çıkışlı? Geçerli bir soru gibi görünüyor ...

belirli sorunuzla ilgisiz (açık find) ancak bu gerçek sorununuzu çözüyor olabilir (ses dosyalarını dönüştürüyor), audiotools.sourceforge.net ve bu örnek duruma (macosx lion için) invibe.net/ LaurentPerrinet / SciBlog / 2012-04-22
meduz

Yanıtlar:


13

findSon çare haricinde çıktıları ayrıştırmaya çalışmayın . Unix dosya sistemlerinde, dosya adlarının dize (yaygın bir yanlış anlama) değil , boş karakter dışında herhangi bir karakter içerebilen ikili bloblar olduğunu anlamak önemlidir /. Dosya adlarını güvenli ve doğru bir şekilde ayrıştırmak, yalnızca% 99'unu tamamen yapmak istemediğiniz bir acıya yeterlidir ( @ yarek'in cevabındakised ifadenin ne kadar tüylü olduğuna ve hatta tüm vakaları kapsamaz) . Neyse ki, bu durumda çok daha basit bir yaklaşım var:

find . -name '*(1).m4a' -execdir sh -c \
'for arg; do mv "$arg" "${arg%(1).m4a}".m4a; done' _ {} \+

temiz bir yaklaşım henüz sed ifade kadar tüylü :) +1
yrk

1
burada bir şeyler eksik ... nerede done?
yrk

@yarek Yakaladığınız için teşekkürler. Bu ve sedboru yaklaşımı arasındaki en büyük fark , bu çok daha güvenli. Bazı temel kabuk komut dosyası yapılarını anlamanız koşuluyla, regex ters eğik çorbadan okumak daha kolaydır.
jw013

Haklısın; bu çok daha temiz. Ve $argdeğişken okumayı çok daha kolay hale getirir.
hobbes3

1
@DQdlM sadece edilir Yukarıdaki haberi pasajı findyürütmesini sholdukça taşınabilir POSIX sözdizimi ile. Daha fazla ayrıntı için göz atmanız için Parametre Genişleme bölümüne , açıklıyor bileşik komutlar bölümünde fordöngü ve POSIX findspec . Bu kaynaklara ek olarak, herhangi yanıtlamaktan mutluluk duyarım belirli sahip soruları.
jw013

6

Debian ve Ubuntu'da rename 's/\(1\)//' *.m4asorununuzu çözmek için kullanabilirim .


Tuhaf, yapabilirim man rename, ama aslında sahip değilim rename: -bash: rename: command not found( which renamehiçbir şey göstermez).
hobbes3

Mac'teki @ hobbes3 , TCL komutunu yeniden adlandır (2) - sistem çağrısı ve yeniden adlandır (n) - man -a renamebulur . Orada ne yeniden adlandırma (1) ne de yardımcı programın kendisi vardır.
yrk

1
IIRC, renamebazı perl kurulumlarında bulunan örneklerle birlikte verilen bir perl betiğidir ve birkaç dağıtım, uygun bir komut olduğu için yola eklenir. (@Hobbes belki internette bulabilirsiniz)
Kevin

@Kevin sistemimde renamenormal ikili (perl değil). Bununla birlikte, başka bir uyarı, tüm normal renameifadelerin desteklenmemesidir. Örneğin sahip olduğum sürüm sadece doğrudan dize değiştirmeleri yapmanıza izin verir, örneğinrename '(1)' '' *.m4a
Patrick

1
Perl renamebetiği yalnızca Debian ve türevleri tarafından yüklenir. Diğer Linux sistemleri farklı bir renameyardımcı programa sahiptir (Patrick tarafından gösterilmiştir). OSX'in ikisi de yok.
Gilles 'SO- kötü olmayı bırak'

4

Zsh'de , zmv kullanarak :

autoload zmv      # you can put this line in your .zshrc
zmv '(*)\(1\)(*)' '$1$2'

İkinci değişken (yeni ad) 'de, $1ve $2parantez grupları anlamına gelir (PATTERN)kaynak desen. Bu yeniden adlandırmayı yazmanın başka bir yolu da

zmv '(*)' '${1/\(1\)/}'

3

Aşağıdaki yaklaşım, oluşturulmuş komutları çalıştırmadan önce önizleme / budama yapabilmenizi sağlar ve çok taşınabilir: sadece basta değil, sadece GNU sed ile değil; find(1) komutu olmayan sistemlerde bile sorunsuz bir şekilde (1) ile değiştirilebilir du.

find . -name '*(1).m4a' |
sed 's/\(.*\)(1).m4a$/mv & \1.m4a/' 

Basılı komutlardan memnunsanız, | sh -xeklenen ile yeniden çalıştırın .

Dosya adlarındaki boşluklarla ilgili endişeleriniz varsa, tüm boşluklardan kaçmak için başka s ekleyin :

find . -name '*(1).m4a' |
sed -e 's/ /\\ /g' -e 's/\(.*\)(1).m4a$/mv & \1.m4a/'

Diğer özel karakterlerin olması bekleniyorsa, biraz daha zorlaşır:

find . -name '*(1).m4a' |
sed -e "s/'/'\\\\''/g" -e 's/\(.*\)(1).m4a$/mv '\''&'\'' '\''\1.m4a'\'/

İlk işlev ', '...'-scaped dizesinin ortasındayken tam anlamıyla alınacak şekilde bir forma dönüştürür . İkinci işlev , argümanları içine alınmış mv komutları üretir '...'.


1
Bu komut dosya adından (boşluklardan (ve diğer tüm özel karakterlerden) kaçmıyor veya dosya adının başına tırnak işaretleri eklemiyor. Komutunuzu değiştirmeyi denedim, ancak mvkomut için her iki dosya adının etrafına nasıl tırnak ekleyeceğimi anlayamadım . Komutunuzdan elde edilen çıktılardan biri mv ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us(1).m4a ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us.m4a. Ve eğer o komutu çalıştırırsam anlarım -bash: syntax error near unexpected token '('.
hobbes3

bu bir ödev olması gerekiyordu :) ama tamam, cevabı güncelleyeceğim
yrk

Bu arada GNU sed, eikame işleminden sonra komut ekleyerek komutun kendisini yürütebilir . Örneğin find . -name '*(1).m4a' | sed 's/\(.*\)(1).m4a$/mv & \1.m4a/e', komut vermeden komutu exexcute eder sh -x.
acele

@ Acele bunu yapan tek sed; ve (hatırlatıyor yine kabuk başlatmak gerekiyor, ancak her komut için bir yenisi make ' Öyle, değil sorunu?)
yrk

2
Aşağıdan oy kullanmamız gerektiğini düşünmüyorum. Ne de olsa geçerli bir çözüm.
hobbes3

1

İşte bunu yapan küçük bir komut dosyası:

for var in `find . -type f -name "*(1).m4a"`; do
    new=`echo $var | cut -d'(' -f1`;
    mv $var $new.m4a;
done

bu, adlarında boşluk bulunan dosyalar üzerinde boğulur; Ayrıca onun için yeterince büyük geçici depolama gerektirir`find ...`
Yrk
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.