
Тестовая среда:
- создайте каталоги из
0
в9
и заполните их файлами изa
вz
$ mkdir {0..9} && touch {0..9}/{a..z}
- Результат
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
Как преобразовать вывод так, чтобы он выглядел следующим образом:
./0a
./0b
...
./9y
./9z
решение1
С помощью отдельной команды Perl rename
:
rename -n 's|/||' */*
Если все в порядке, удалите -n
, а затем удалите оставшиеся пустые каталоги.
rmdir {0..9}
решение2
С помощью инструментов POSIX,
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
вызывает оболочку и выполняет цикл for для каждого файла.
dirn="${f%/*}"
получает имя родительского каталога, исключая все, что находится после (и включая) последнюю косую черту в имени файла.${f##*/}
получает имя файла без пути, исключая все, что находится до (и включая) последнюю косую черту в имени файла.
Эти две конструкции оболочки делают то же самое, чтоdirname
иbasename
, поэтому эквивалентная форма команды —
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
, хотя этот вариант должен быть медленнее, поскольку ему необходимо запустить два дополнительных процесса для каждого файла.
Если вам не нужно переходить более чем в один каталог, как показано в вашем примере, это можно сделать с помощью простого цикла оболочки:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done