![Выравнивание структуры папок](https://rvso.com/image/36020/%D0%92%D1%8B%D1%80%D0%B0%D0%B2%D0%BD%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B%20%D0%BF%D0%B0%D0%BF%D0%BE%D0%BA.png)
У меня такая структура папок:
├── foo1
│ ├── bar1.txt
│ └── bar2.txt
├── foo2
│ ├── bar3.txt
│ └── bar4 with a space.txt
└── foo3
└── qux1
├── bar5.txt
└── bar6.txt
которые я хотел бы свести к следующему, с подчеркиванием между каждым уровнем папок:
├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt
Я поискал и не нашел ни одного работающего решения, в основном потому, что, как мне кажется, у моей проблемы есть две особенности: внутри корневой папки может быть несколько уровней папок, а также потому, что некоторые файлы могут содержать пробелы.
Есть идеи, как это сделать в bash? Спасибо!
Редактировать: Бегущий Глин Джекман предложил ответ Я получаю это:
Для папки первого уровня есть два подчеркивания. Есть идеи, как этого избежать или просто переименовать так, чтобы было только одно подчеркивание? Спасибо.
решение1
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;
удалите echo
, если вы удовлетворены тем, что это работает. Не беспокойтесь, что команды, отображаемые с помощью echo, не показывают кавычек, скрипт будет правильно обрабатывать файлы с пробелами.
Если вы хотите удалить пустые подкаталоги:
find */ -depth -type d -exec echo rmdir '{}' \;
решение2
Используя переименование perl:
find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;
ВЫХОД
$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt
ПРИМЕЧАНИЕ
- Я используюнегативный взгляд позади
(?<!\.)
не трогать первый./
Я сохраняю пустые директории, не стесняйтесь:
find . -depth -type d -exec rm {} \;
Существуют и другие инструменты с таким же названием, которые могут или не могут сделать то же самое, поэтому будьте осторожны.
Если вы выполните следующую команду ( GNU
)
$ file "$(readlink -f "$(type -p rename)")"
и у вас есть такой результат
.../rename: Perl script, ASCII text executable
и не содержащие:
ELF
тогда это, кажется, правильный инструмент =)
Если нет, сделать его значением по умолчанию (обычно это уже так) Debian
и производным, например Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(замените /path/to/rename
на путь вашей perl's rename
команды.
Если у вас нет этой команды, найдите ее в менеджере пакетов, чтобы установить, илисделать это вручную
И последнее, но не менее важное: этот инструмент изначально был написан Ларри Уоллом, отцом Perl.
решение3
сpax
...
pax -Xrwls '|/|_|g' */ "$PWD"
Это создаст жесткую ссылку в текущем каталоге на все файлы в его дочерних каталогах с _
заменой на /
. Затем вы можете проверить результаты и удалить все дочерние каталоги с помощью...
rm -rf */
...как только вы убедитесь, что результаты вас устраивают.
решение4
Вы можете попробовать выполнить команду ниже.
$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;
Приведенная выше команда переместит файлы, а каталог останется, и его можно будет удалить позже.
$ ls
foo1_bar1.txt foo1_bar2.txt foo2_bar3.txt foo2_bar4.txt foo3_bar5.txt foo3_bar6.txt