Bagaimana cara menyalin dan mengganti nama file dalam "find" berfungsi Linux?

17

Saya memiliki folder bernama /home/user/tempsyang memiliki 487 folder. Di setiap folder saya memiliki file bernama thumb.png.

Saya ingin menyalin semua file bernama thumb.png ke folder terpisah dan menamainya berdasarkan folder asalnya.

Fatamorgana
sumber
ganti nama mereka, bagaimana? Jika Anda mengganti pembatas direktori dengan sesuatu - misalkan menggarisbawahi (_), Anda mungkin mendapatkan tabrakan dengan file, yang sudah berisi garis bawah. Itu berlaku untuk setiap karakter yang valid, dan selain / dan \ 0, yang dilarang dalam nama file, tidak ada pelabuhan yang aman - karakter apa pun dapat menghasilkan tabrakan.
pengguna tidak diketahui
Apakah folder memiliki subfolder, atau hanya folder sederhana, struktur lebar?
pengguna tidak diketahui

Jawaban:

8

Ini dia:

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

edit:

omong-omong kanonis, omong-omong, adalah bahwa menggunakan finduntuk ini adalah ide yang buruk - hanya menggunakan ekspansi shell jauh lebih dapat diandalkan. Juga, ini mengasumsikan bash, tapi saya pikir itu asumsi yang aman :)

edit 2:

untuk kejelasan, saya akan memecahnya:

# 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;

detail pada ${var/Pattern/Replacement}konstruk dapat ditemukan di sini .

tanda kutip di cpbaris penting untuk menangani spasi dan baris baru, dll. dalam nama file.

simon
sumber
new_file = new_folder? Apa tujuan dari garis miring terbalik di depan garis miring new_file/\/thumb?
pengguna tidak diketahui
1
@user: ${VARIABLE/PATTTERN/REPLACEMENT}menghasilkan nilai VARIABLEtetapi dengan pola yang diganti oleh teks pengganti. Di sini polanya /thumb( /kebutuhan untuk melarikan diri sehingga tidak terlihat ${new_file//PATTERN/REPLACEMENT}, yang menjadikannya pengganti global alih-alih pengganti yang muncul pertama kali) dan teks pengganti kosong.
Gilles 'SO- stop being evil'
Tentu saja, sekarang saya melihatnya. :)
pengguna tidak diketahui
1
Anda mengasumsikan bahwa 487 direktori berada langsung di bawah /home/user/temps, yang tidak jelas dari pertanyaan. Jika tidak, Anda perlu mencari atau **.
Gilles 'SO- berhenti menjadi jahat'
@Gilles - Memang, itulah cara saya membaca pertanyaan. Hargai poinnya, :)
simon
5

Ini berfungsi untuk subdirektori dalam yang sewenang-wenang:

$ 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'

Bagian interessting adalah ekspansi parameter ${NAME//\//_} . Dibutuhkan konten NAME, dan menggantikan setiap kejadian /dengan _.

Catatan: hasilnya tergantung pada direktori kerja dan parameter path untuk find. Saya menjalankan perintah dari direktori induk temps. Ganti cpdengan echopercobaan.

lesmana
sumber
Gagal pada file yang berisi baris baru dalam namanya.
pengguna tidak diketahui
Itu bekerja dengan sangat baik. satu hal lagi, saya punya beberapa file zip di beberapa sub direktori juga. apakah mungkin untuk mengekstrak imgae dari sana juga. ingat 'zip not tar'
Mirage
1

Kode pembantu pendek:

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

beri nama 'deslash.sh' dan buat itu dapat dieksekusi. Sebut saja dengan:

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

Ini akan gagal, jika ada tabrakan

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

tapi itu tidak bisa dihindari.

Pengguna tidak diketahui
sumber
0

Coba ini

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

Edit

Saya telah menambahkan penawaran jika ada nama dir Anda yang memiliki karakter white-space yang tertanam di dalamnya.

Saya juga telah mengubah ini jadi itu hanya akan mencetak perintah yang akan dieksekusi. Periksa output skrip untuk memastikan semua file / nama path terlihat benar. Saat Anda yakin tidak ada masalah dengan perintah yang akan dieksekusi, hapus echo.

pemukul
sumber
Saya punya beberapa file png di beberapa subfolder lagi, dapatkah itu bekerja
Mirage
untuk mv -i ./A A/thumb.png ../tmp/.pngfolder "A A" saya, ia menghasilkan: - semua file diakhiri dengan ../tmp/.png (../tmp adalah dir target saya).
pengguna tidak diketahui
Tambahkan tanda kutip dan kurung kurawal di sekitar semua variabel dalam kode di atas, yaitu "$ {dir}"
shellter
@ Mirror51 menulis: "file dalam beberapa subfolder lagi, apakah itu akan berfungsi". Ya seharusnya. Tahukah Anda bahwa Anda dapat menjalankan setiap langkah skrip ini secara terpisah (atau saat disatukan, setiap set pipa). Anda dapat menjalankan find -type ddan melihat hasilnya. Apakah itu mendapatkan semua direktori yang Anda harapkan? Seharusnya, jika tidak, tambahkan beberapa output untuk menunjukkan masalah. Semoga berhasil.
shellter
Tidak akan bekerja read dirmelakukan pemisahan kata, dan mengambil, dari direktori a\nba dan b sebagai dua contoh, yang tidak bisa diselesaikan oleh masking.
pengguna tidak diketahui
-1

Untuk menyalin Anda memerlukan perintah cp , dan untuk mengganti nama untuk linux sama dengan memindahkan file, jadi Anda harus melakukannya dengan perintah mv . Di Linux Anda selalu harus menentukan keseluruhan path, dari sumbernya, jika Anda berada di folder lain, dan ke folder tujuan, tentu saja. Saya akan menjadi seperti ini, untuk salinan:

cp /source_path/file /destination_path/

atau untuk mengganti nama atau pindah

mv /source_path/old_file /destination_path/new_name_file

sumber
Ini hanya sebagian kecil dari pertanyaan poster itu. Sekarang jelaskan bagaimana cara mengulangi direktori dan salin thumbnail :-)
OP ingin menggunakanfind
Ya, Anda benar ... Saya tidak tahu apa yang terjadi pada saya ...