переместить файлы на уровень выше, добавив имя папки к имени файла?

переместить файлы на уровень выше, добавив имя папки к имени файла?

Тестовая среда:

  • создайте каталоги из 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

Связанный контент