Copie nomes de arquivos e adicione o prefixo do caminho, em um diretório, recursivamente

1

Eu tenho um diretório de trabalho: /home/myusername/projectdir
O diretório de trabalho contém arquivos e subdiretórios. A profundidade dos subdiretórios não é conhecida.
Eu quero colocar todos os arquivos *.log no mesmo diretório de saída, com os nomes de base prefixados com o caminho do subdiretório (substituindo / with # ).

Exemplo:

/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

Eu tentei isso:

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

Como posso fazer isso com mais elegância?

    
por BlackCat 23.08.2015 / 14:10

3 respostas

1

Usando spaces -delimited strings, isso pode manipular \n e mkdir -p em nomes de arquivos.

cd "${PROJECT_DIR%/*}"
outdir="output"; mkdir -p "$outdir"
find "$PROJECT_DIR" -type f -name '*.log' -printf "%p
projectdir
├── file0.txt
├── file1.log
└── subdir
    ├── file2.log
    └── subsubdir
        └── file3.log

2 directories, 4 files
${outdir}/%P
output
├── file1.log
├── #subdir#file2.log
└── #subdir#subsubdir#file3.log

0 directories, 3 files
" | awk 'BEGIN{FS="/";RS=ORS="
cd "${PROJECT_DIR%/*}"
outdir="output"; mkdir -p "$outdir"
find "$PROJECT_DIR" -type f -name '*.log' -printf "%p
projectdir
├── file0.txt
├── file1.log
└── subdir
    ├── file2.log
    └── subsubdir
        └── file3.log

2 directories, 4 files
${outdir}/%P
output
├── file1.log
├── #subdir#file2.log
└── #subdir#subsubdir#file3.log

0 directories, 3 files
" | awk 'BEGIN{FS="/";RS=ORS="%pre%"} NR%2||NF==2 {print; next} {gsub("/","#"); sub("#","/#"); print}' | xargs -0 -n2 cp -T
"} NR%2||NF==2 {print; next} {gsub("/","#"); sub("#","/#"); print}' | xargs -0 -n2 cp -T
  • find cria o diretório de destino (nenhum erro, se já existir).
  • %P imprime find -delimited file-paths ( $1 significa sem awk % path_do% directory-path).
  • cp cria os 2 caminhos de arquivo exigidos por xargs , como dois registros delimitados por cp -T .
  • tree lê os caminhos de arquivo tree -delimited, 2 por vez, e os passa para %code%

Aqui está %code% do diretório source de teste '

%pre%

Aqui está o %code% do diretório destino '

%pre%     
por 23.08.2015 / 18:32
1

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

  • cd para o diretório do projeto
  • encontre todos os arquivos de log
  • lista de arquivos de log do tar para stdout
  • cd para o diretório de saída
  • untar stdin
por 23.08.2015 / 15:14
1
#!/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 
    
por 23.08.2015 / 15:23