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

У меня есть рабочий каталог: /home/myusername/projectdir
Рабочий каталог содержит файлы и подкаталоги. Глубина подкаталогов неизвестна.
Я хочу поместить все файлы *.log в один и тот же выходной каталог с базовыми именами с префиксом пути подкаталога (substitutin / with # ).

Пример:

  • как искать файл для начала строки и сохранять переменную
  • Debian и Systemd: ошибка прерывания цикла заказа
  • libvirt мостовой KVM vm не может маршрутизировать
  • Добавление «случайной числовой энтропии» для ключей GPG?
  • Что такое curl-эквивалент этой команды wget?
  • Как исправить эту ошибку? make: *** Ошибка 1
  •  /home/myusername/projectdir/file1.log -> /home/myusername/output/file1.log /home/myusername/projectdir/subdir/file2.log -> /home/myusername/output/#subdir#file2.log /home/myusername/projectdir/subdir/subsubdir/file3.log -> /home/myusername/output/#subdir#subsubdir#file3.log 

    Я попробовал это:

     cd "$PROJECT_DIR" CDIR="" for x in **/*.log; do if [ "$CDIR" != "$PROJECT_DIR/${x%/*}" ]; then CDIR="$PROJECT_DIR/${x%/*}" SUBDIR="${x%/*}" PREFIX=${SUBDIR//'/'/'#'} cd "$CDIR" for FILENAME in *.log; do NEWNAME="#$PREFIX#$FILENAME" cp "$FILENAME" "$OUTPUT_DIR/$NEWNAME" done fi done 

    Как я могу сделать это более элегантно?

  • vim слишком медленный при сохранении файлов
  • Код работает вручную на терминале, но не может запускать скрипт
  • какая оболочка будет использовать sudo для выполнения сценария оболочки без строки shebang
  • Доступ 2 виртуальных машин с одним IPv4
  • Разрешения mkdir не соответствуют umask (изменение зависит от местоположения)
  • linux: Как я могу просмотреть все UUID для всех доступных дисков в моей системе?
  • 3 Solutions collect form web for “Скопируйте имена файлов и добавьте префикс пути в каталог, рекурсивный”

    С помощью \0 -пределенных строк это может обрабатывать spaces и \n в именах файлов.

     cd "${PROJECT_DIR%/*}" outdir="output"; mkdir -p "$outdir" find "$PROJECT_DIR" -type f -name '*.log' -printf "%p\0${outdir}/%P\0" | awk 'BEGIN{FS="/";RS=ORS="\0"} NR%2||NF==2 {print; next} {gsub("/","#"); sub("#","/#"); print}' | xargs -0 -n2 cp -T 
    • mkdir -p создает целевой каталог (нет ошибки, если он уже существует).
    • find prints \0 -delimited file-paths ( %P означает, что не найден путь к каталогу $1 ).
    • awk создает 2 файла-пути, требуемые cp , как две записи с разделителями \0 .
    • xargs читает \0 -пределенные файловые пути, 2 за раз и передает их в cp -T

    Вот tree исходного каталога теста `

     projectdir ├── file0.txt ├── file1.log └── subdir ├── file2.log └── subsubdir └── file3.log 2 directories, 4 files 

    Вот tree каталога назначения `

     output ├── file1.log ├── #subdir#file2.log └── #subdir#subsubdir#file3.log 0 directories, 3 files 

    (cd "$PROJECT_DIR" && find . -name "*.log") | tar -cf - -T - | (cd $OUTPUT_DIR && tar -xf -)

    • cd в каталог проекта
    • найти все файлы журнала
    • Список файлов журналов tar в stdout
    • cd для вывода каталога
    • untar stdin
     #!/bin/bash newdir=/absolute/path/output olddir=/absolute/path/project find $olddir -name '*log' | while read line ; do if [ "$olddir" == "$( basename "$line" )" ] ; then #just move the file if there are no subdirectories mv "$line" "$newdir" else #1) replace old project dir with nothing #2) replace all slashes with hashes #3) set new outdir as prefix #4) hope that there are no colons in the filenames prefix="$( sed -e "s:$olddir::" -e 's:/:#:g' -e "s:^:$newdir/:" <<<"$( dirname "$line")" )" mv "$line" "$prefix"#"$( basename "$line" )" fi done 
    Linux и Unix - лучшая ОС в мире.