Сглаживание сложных структур папок с дублирующимися именами файлов

У меня есть папка со сложной структурой папок:

├── folder1 │ ├── 0001.jpg │ └── 0002.jpg ├── folder2 │ ├── 0001.jpg │ └── 0002.jpg ├── folder3 │ └── folder4 │ ├── 0001.jpg │ └── 0002.jpg └── folder5 └── folder6 └── folder7 ├── 0001.jpg └── 0002.jpg 

Я хотел бы сгладить структуру папок таким образом, чтобы все файлы находились в родительском каталоге с уникальными именами, такими как folder1_0001.jpg, folder1_0002.jpg … folder5_folder6_folder7_0001.jpg и т. Д.

Я попытался использовать код, предложенный в разделе «Сглаживание папки»,

 $ find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \; 

echo демонстрирует, что оно работает:

 mv folder3/folder4/000098.jpg folder3_folder4_000098.jpg 

Но выходные файлы не помещаются в родительский каталог. Я искал весь диск и не могу найти выходные файлы.

Я также попытался «Сгладить структуру папок с именем файла в Bash»

 $ find . -type f -name "*.jpg" | sed 'h;y/\//_/;H;g;s/\n/ /g;s/^/cp -v /' | sh 

-v показывает, что он работает:

 './folder3/folder4/000098.jpg' -> '._folder3_folder4_000098.jpg' 

Однако вывод создает скрытые файлы в родительском каталоге, что усложняет мой рабочий процесс. Я могу просмотреть эти скрытые файлы в родительском каталоге, используя ls -a

Я также попробовал предложенный ниже код из «Переименование дубликатов файлов с помощью команды сгладить папки»

 find . -mindepth 2 -type f | xargs mv --backup=numbered -t . && find . -type d -empty -delete 

Но команда перезаписывает файлы с похожими именами файлов.

Любые предложения о том, как сгладить сложную структуру папок без перезаписи файлов с похожими именами? Существующие решения, похоже, работают только на структурах папок на один уровень.

Моя конечная цель – преобразовать уникальные имена в последовательные номера, как описано в разделе «Переименование файлов в папке на последовательные номера»,

  a=1 for i in *.jpg; do new=$(printf "%04d.jpg" "$a") #04 pad to length of 4 mv -- "$i" "$new" let a=a+1 done 

  • Удалить все файлы в каталоге
  • Как получить список затронутых файлов между двумя точками времени?
  • Помогла ли моя команда $ mv '* .mobi' соединить мои файлы?
  • Определите, был ли файл изменен
  • Файл загадочно пуст. Варианты восстановления?
  • Проверьте, есть ли файлы, соответствующие шаблону, чтобы выполнить скрипт
  • Могу ли я получить «du», сгруппированный по месяцам?
  • Файл с разрешениями --- S - l ---
  • 4 Solutions collect form web for “Сглаживание сложных структур папок с дублирующимися именами файлов”

    Я понятия не имею, почему первое решение в вашем вопросе не сработало. Я могу только предположить, что вы забыли удалить echo . Как бы то ни было, вот еще один подход, который также должен делать то, что вам нужно, если вы используете bash :

     shopt -s globstar for i in **/*jpg; do mv "$i" "${i//\//_}"; done 

    объяснение

    • shopt -s globstar включает shopt -s globstar от bash, которая ** рекурсивно соответствует любому количеству каталогов или файлов.
    • for i in **/*jpg; будет перебирать все файлы (или каталоги), чье имя заканчивается на .jpg , сохраняя каждый как $i .
    • "${i//\//_}" – это имя текущего файла (или каталога) со всеми экземплярами / замененными на _ .

    Если вы также можете иметь каталоги с именами, заканчивающимися на .jpg и хотите пропустить их, сделайте это вместо этого:

     shopt -s globstar for i in **/*jpg; do [ -f "$i" ] && echo mv "$i" "${i//\//_}"; done 

    И для всех файлов, независимо от расширения:

     shopt -s globstar for i in **/*; do [ -f "$i" ] && echo mv "$i" "${i//\//_}"; done 

    Если у вас есть rename Perl (иногда называемое prename ), вы можете сделать это:

     find folder* -type f -name '*.jpg' -exec rename 's!/!_!g' {} \; 

    Это берет каждый путь к имени файла и заменяет все вхождения / с _ .

    Если вы действительно хотите переименовать файлы в ряд последовательных четырехзначных имен файлов, вы можете использовать их в своем исходном наборе данных. Он будет работать только там, где имена каталогов и файлов содержат регулярные буквенно-цифровые символы (в частности, он будет терпеть неудачу, если присутствует пробел, пунктуация оболочки или другие пробелы):

     rename 's!.*!sprintf "%04d.jpg", ++$a!e' $(find folder* -type f -name '*.jpg' | sort) 

    Используйте rename -n ... чтобы узнать, что произойдет с ним, изменив что-либо, или используйте rename -v ... чтобы наблюдать, как это происходит.

     pax -rws'|/|_|g' folder*/ . 

    … будет работать до тех пор, пока не будет возможности перекрывать имена файлов te. Чтобы сделать это более безопасно, используйте опцию -l link и зеркало дерева к другому пути, затем осмотрите новое дерево перед удалением старого.

    Мне удался следующий скрипт:

     #!/bin/sh for folder in $(ls $1) do for file in $(ls ${folder}) do mv ${folder}/${file} $1/${folder}_${file} done rmdir ${folder} done 
    Linux и Unix - лучшая ОС в мире.