1

Я работаю с деревом папок и файлов со структурой

  • \ Рассказы \ 00 \ 0 \ 00000 \ temp.xxx
  • \ Рассказы \ 00 \ 0 \ 00001 \ temp.xxx
  • ...
  • \ История \ 10 \ 5 \ 10552 \ temp.xxx
  • \ История \ 10 \ 5 \ 10553 \ temp.xxx
  • ...
  • \ История \ 45 \ 9 \ 45998 \ temp.xxx
  • \ История \ 45 \ 9 \ 45999 \ temp.xxx

Что мне нужно, это переименовать файлы так, чтобы temp.xxx был изменен на последовательное имя файла, как показано ниже:

  • \ Рассказы \ 00 \ 0 \ 00000 \ 00000.xxx
  • \ Рассказы \ 00 \ 0 \ 00001 \ 00001.xxx
  • ...
  • \ История \ 10 \ 5 \ 10552 \ 10552.xxx
  • \ История \ 10 \ 5 \ 10553 \ 10553.xxx
  • ...
  • \ История \ 45 \ 9 \ 45998 \ 45998.xxx
  • \ История \ 45 \ 9 \ 45999 \ 45999.xxx

2 ответа2

0

Вы можете сделать это с помощью команды:

find . -name "temp*" | sed -E 's|(.*)\/(.*)\/temp(.[a-z]{3})|mv & \1\/\2\/\2\3|g' | source /dev/stdin

Пошаговое объяснение.

Это ваш пример ввода:

$ find . -name "temp*"
./History/10/5/10552/temp.xxx
./History/10/5/10553/temp.xxx
./Stories/00/0/00000/temp.xxx
./Stories/00/0/00001/temp.xxx

Я настраиваю вывод в соответствии с требуемым выводом.

$ find . -name "temp*" | sed -E 's|(.*)\/(.*)\/temp(.[a-z]{3})|\1\/\2\/\2\3|g'
./History/10/5/10552/10552.xxx
./History/10/5/10553/10553.xxx
./Stories/00/0/00000/00000.xxx
./Stories/00/0/00001/00001.xxx

Таким образом, мы преобразуем каждый temp* в команду mv с необходимыми именами вывода. Команда выглядит так:

$ find . -name "temp*" | sed -E 's|(.*)\/(.*)\/temp(.[a-z]{3})|mv & \1\/\2\/\2\3|g'
mv ./History/10/5/10552/temp.xxx ./History/10/5/10552/10552.xxx
mv ./History/10/5/10553/temp.xxx ./History/10/5/10553/10553.xxx
mv ./Stories/00/0/00000/temp.xxx ./Stories/00/0/00000/00000.xxx
mv ./Stories/00/0/00001/temp.xxx ./Stories/00/0/00001/00001.xxx

Чтобы выполнить каждую команду из предыдущего вывода, мы должны добавить | source /dev/stdin в конце команды.

Результаты будут следующими:

$ find . -name "*.xxx"
./History/10/5/10552/10552.xxx
./History/10/5/10553/10553.xxx
./Stories/00/0/00000/00000.xxx
./Stories/00/0/00001/00001.xxx
0

Если ваша структура однородна, и у вас есть глубина 3 внутри вашей папки «История», возможно, интуитивно понятным способом было бы использовать вложенные циклы, а затем использовать mv для переименования.

В следующем коде предполагается, что у вас есть один файл в каждой папке в layer3, и ваша /History не содержит ничего, кроме каталогов.

for layer1 in /History/*; do
    for layer2 in /History/$layer1/*; do
        for layer3 in /History/$layer1/$layer2/*; do
           for files in /History/$layer1/$layer2/$layer3/*; do
                mv files $layer3.xxx
            done
        done
    done
done

возможно, эти две ссылки также полезны:

http://www.cyberciti.biz/faq/bash-for-loop/

https://stackoverflow.com/questions/539583/how-do-i-recursively-list-all-directories-at-a-location-breadth-first

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .