Як скопіювати та перейменувати файли, знайдені у функції «знайти» Linux?


17

Я маю папку з іменем /home/user/temps487 папок. У кожній папці є файл під назвою thumb.png.

Я хочу скопіювати всі файли з ім'ям thumb.png в окрему папку та перейменувати їх на основі папки, з якої вони вийшли.


перейменувати їх, як? Якщо ви заміните роздільник обмежень каталогу чимось - скажімо, підкреслити (_), у вас можуть виникнути зіткнення з файлами, які вже містять підкреслення. Це справедливо для кожного дійсного символу, а крім / і \ 0, заборонених у файлах файлів, немає безпечної гавані - будь-який символ може спричинити зіткнення.
користувач невідомий

Чи мають папки папки або просто просту широку структуру папок?
користувач невідомий

Відповіді:


8

Ось вам:

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

редагувати:

Канонічна мудрість, до речі, полягає в тому, що використовувати findдля цього погану ідею - просто використовувати розширення оболонки набагато надійніше. Також це передбачає bash, але я вважаю, що це безпечне припущення :)

редагувати 2:

для наочності я розбию його:

# 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}конструкцію можна знайти тут .

лапки в cpрядку важливі для обробки пробілів та нових рядків тощо у назви файлів.


new_file = new_folder? Яка мета зворотної косої риси перед косою рисою new_file/\/thumb?
користувач невідомий

1
@user: ${VARIABLE/PATTTERN/REPLACEMENT}створює значення, VARIABLEале з малюнком, заміненим текстом заміни. Тут викрійка /thumb( /потрібно уникнути, щоб вона не виглядала ${new_file//PATTERN/REPLACEMENT}, що робить її глобальною заміною замість заміни першого появи), а текст заміни порожній.
Жил "ТАК - перестань бути злим"

Звичайно, зараз я це бачу. :)
користувач невідомий

1
Ви припускаєте, що 487 каталогів знаходяться безпосередньо під /home/user/temps, що не зрозуміло з питання. Якщо це не так, вам потрібно знайти або **.
Жил "ТАК - перестань бути злим"

@Gilles - Я справді, саме так я читав питання. Вдячний за все, однак :)
simon

5

Це працює для довільно глибоких підкаталогів:

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

Цікавою частиною є розширення параметра ${NAME//\//_} . Він приймає зміст NAME, і замінює всі входження /з _.

Примітка: результат залежить від робочого каталогу та параметра шляху для пошуку. Я виконав команду з батьківського каталогу temps. Замінити cpз echoекспериментом.


Помилка у файлах, що містять нову рядок у своєму імені.
користувач невідомий

Добре, що працювало дуже добре. Ще одне, у мене також є кілька поштових файлів у деяких підкаталогах. чи можна витягувати і там же імги. пам’ятайте 'zip not tar'
Міраж

1

Короткий довідковий код:

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

давайте назвемо його "deslash.sh" і зробимо його виконуваним. Телефонуйте за допомогою:

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

Це не вдасться, якщо зіткнення буде

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

але це неминуче.


0

Спробуйте це

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

Редагувати

Я додав цитування, якщо будь-яке з ваших імен режисера має вбудовані символи пробілів.

Також я змінив це, щоб він тільки роздрукував команди, які потрібно виконати. Перевірте вихід сценарію, щоб переконатися, що всі файли / імена виглядають належним чином. Коли ви впевнені, що немає проблем з командами, які будуть виконуватися, видаліть echo.


У мене є деякі файли png у деяких інших папках, чи це буде працювати
Mirage

для моєї папки "A" вона створює: mv -i ./A A/thumb.png ../tmp/.png- всі файли закінчуються ../tmp/.png (../tmp - мій цільовий реж).
користувач невідомий

Додайте лапки та фігурні дужки навколо всіх змінних у вищевказаному коді, тобто "$ {dir}"
оболонка

@ Mirror51 писав: "Файли в деяких інших папках, це буде працювати". Так, слід. Чи знаєте ви, що можете виконувати кожен крок цього сценарію окремо (або, коли з'єднані, кожен набір труб). Ви можете виконати тільки find -type dта побачити вихід. Це отримує всі очікувані вами каталоги? Якщо ні, то, будь ласка, додайте трохи результатів, щоб показати проблему. Щасти.
обстріл

Не буде працювати. read dirвиконує розбиття слів і бере з каталогу a\nba і b два екземпляри, які жодне маскування не може вирішити.
користувач невідомий

-1

Для копіювання вам потрібна команда cp , а перейменування на Linux - це те саме, що і переміщення файлу, тому вам доведеться це робити з командою mv . У Linux завжди потрібно вказати весь шлях, починаючи від джерела, якщо ви перебуваєте в іншій папці, і до папки призначення, звичайно. Я б щось подібне, для копії:

cp /source_path/file /destination_path/

або перейменувати чи перемістити

mv /source_path/old_file /destination_path/new_name_file

Це лише незначна частина запитання плаката. Тепер поясніть, як перебирати каталоги та копіювати ескізи :-)

ОП хоче використовуватиfind

Так, ти маєш рацію ... Я не знаю, що зі мною сталося ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.