Linux "find" işlevinde bulunan dosyaları nasıl kopyalayıp yeniden adlandırırsınız?


17

/home/user/temps487 klasör içeren bir klasör var . Her klasörde thumb.png adlı bir dosyam var.

Thumb.png adlı tüm dosyaları ayrı bir klasöre kopyalamak ve geldikleri klasöre göre yeniden adlandırmak istiyorum.


onları yeniden adlandır, nasıl? Dizin sınırlayıcıyı bir şeyle değiştirirseniz, diyelim ki alt çizgi (_) diyelim, zaten alt çizgi içeren dosyalarla çakışmalar alabilirsiniz. Bu geçerli her karakter için geçerlidir ve dosya adlarında yasak olan / ve \ 0 yanında güvenli bir liman yoktur - herhangi bir karakter bir çarpışma yaratabilir.
kullanıcı bilinmiyor

Klasörlerin alt klasörleri mi yoksa yalnızca düz, geniş bir klasör yapısı mı var?
kullanıcı bilinmiyor

Yanıtlar:


8

Hadi bakalım:

for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;

Düzenle:

kanonik bilgelik, bu arada, bunun findiçin kötü bir fikir olduğudur - sadece kabuk genişletmeyi kullanmak çok daha güvenilirdir. Ayrıca, bu varsayılır bash, ancak bunun güvenli bir varsayım olduğunu anlıyorum :)

düzenleme 2:

açıklık için, onu yıkacağım:

# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do

    # replace 'temps' with 'new_folder' in the path
    # '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
    new_file=${file/temps/new_folder};

    # drop '/thumb' from the path
    # '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
    cp "$file" "${new_file/\/thumb/}";
done;

${var/Pattern/Replacement}yapı ile ilgili detaylar burada bulunabilir .

cpsatırdaki alıntılar dosya adlarındaki boşlukları ve satırsonlarını vb. işlemek için önemlidir.


new_file = new_folder? Eğik çizginin önündeki ters eğik çizginin amacı nedir new_file/\/thumb?
kullanıcı bilinmiyor

1
@ kullanıcı: deseni ${VARIABLE/PATTTERN/REPLACEMENT}üretir VARIABLEancak kalıp yerine yedek metnin yerini alır. Burada desen /thumb(ilk /görünme ${new_file//PATTERN/REPLACEMENT}yerine global bir değiştirme yapan, görünmemesi için kaçması gerekir ) ve değiştirme metni boştur.
Gilles 'SO- kötü olmayı bırak'

Tabii ki, şimdi görüyorum. :)
kullanıcı bilinmiyor

1
487 dizinlerinin doğrudan altında olduğunu varsayıyorsunuz /home/user/temps, ki bu sorudan net değil. Eğer böyle değilse, sen gerek bulmak ya **.
Gilles 'SO- kötü olmayı bırak'

@Gilles - Ben gerçekten, soruyu bu şekilde okudum. Yine de noktayı takdir edin :)
simon

5

Bu, keyfi olarak derin alt dizinler için çalışır:

$ find temps/ -name "thumb.png" | while IFS= read -r NAME; do cp -v "$NAME" "separate/${NAME//\//_}"; done
`temps/thumb.png' -> `separate/temps_thumb.png'
`temps/dir3/thumb.png' -> `separate/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `separate/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `separate/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `separate/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `separate/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `separate/temps_dir2_dir21_thumb.png'

Aradaki kısım parametre genişletmedir ${NAME//\//_} . Bu içeriği alır NAMEve her oluşumunu değiştirir /ile _.

Not: sonuç, çalışma dizinine ve find için path parametresine bağlıdır. Komutu temps'in üst dizininden yürüttüm. Denemek için cpile değiştirin echo.


Adlarında yeni satır içeren dosyalarda başarısız olur.
kullanıcı bilinmiyor

Çok iyi çalıştı. bir şey daha, bazı alt dizinlerde de birkaç zip dosyaları var. oradan da imga çıkarmak mümkün mü? 'zip not tar' hatırlayın
Mirage

1

Kısa yardımcı kodu:

#!/bin/bash
#
# echo cp "$1" ../tmp/"${1//\//_}" 
#
mv "$1" ../tmp/"${1//\//_}"

hadi 'deslash.sh' adını verelim ve çalıştırılabilir yapalım. Şununla ara:

find -type f -name thumb.png -exec ./deslash.sh {} ";"    

Bir çarpışma olursa başarısız olur

a/b/thumb.png # and 
a_b/thumb.png 

ama bu kaçınılmaz.


0

Bunu dene

mkdir /home/user/thumbs
targDir=/home/user/thumbs

cd /home/user/temps

find . -type d | 
 while IFS="" read -r dir ; do
   if [[ -f "${dir}"/thumb.png ]] ; then
     echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
   fi
done

Düzenle

Ben dir isimlerinden herhangi birinde beyaz boşluk karakterleri gömülü olması durumunda alıntı ekledim.

Ayrıca bunu değiştirdim, böylece sadece çalıştırılacak komutları yazdıracağım. Tüm dosyaların / yol adlarının düzgün göründüğünden emin olmak için komut dosyasının çıktısını inceleyin. Yürütülecek komutlarla ilgili herhangi bir sorun olmadığından emin olduğunuzda echo,.


Bazı daha alt klasörlerde bazı png dosyaları var, bu işe yarayacak
Mirage

benim "A A" klasörüm için, üretir: mv -i ./A A/thumb.png ../tmp/.png- tüm dosyalar ../tmp/.png ile biter (../tmp hedef hedefimdir).
kullanıcı bilinmiyor

Yukarıdaki koddaki tüm değişkenlerin etrafına tırnak işaretleri ve süslü parantezler ekleyin, örn. "$ {Dir}"
shellter

@ Mirror51 şunu yazdı: "bazı alt klasörlerdeki dosyalar işe yarayacak mı". Evet olmalı. Bu komut dosyasının her bir adımını ayrı olarak (veya her boru hattında, her boru kümesini) çalıştırabileceğinizi biliyor muydunuz? Sadece ve yürütme find -type dçıktısını görebilirsiniz. Bu beklediğiniz tüm dizinleri alıyor mu? Değilse, sorunu göstermek için lütfen bir miktar çıktı ekleyin. İyi şanslar.
shellter

Çalışmayacak. read dirkelime bölme işlemini gerçekleştirir ve a\nba ve b dizininden hiçbir maskelemenin çözemediği iki örnek olarak alır .
kullanıcı bilinmiyor

-1

Kopyalamak için cp komutuna ihtiyacınız vardır ve linux için yeniden adlandırmak dosyayı taşımaktan farklıdır , bu yüzden mv komutuyla yapmanız gerekir . Linux'ta her zaman, başka bir klasördeyseniz ve hedef klasöre kaynaktan tüm yolu belirtmeniz gerekir. Kopya için şöyle bir şey olurdum:

cp /source_path/file /destination_path/

veya yeniden adlandırmak veya taşımak için

mv /source_path/old_file /destination_path/new_name_file

Bu posterin sorusunun sadece küçük bir kısmı. Şimdi dizinler üzerinde nasıl yineleneceğini açıklayın ve küçük resimleri kopyalayın :-)

OP kullanmak istiyorfind

Evet, haklısın ... Bana ne olduğunu bilmiyorum ...
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.