在目录中递归复制文件名并添加路径前缀

在目录中递归复制文件名并添加路径前缀

我有一个工作目录:/home/myusername/projectdir
工作目录包含文件和子目录。子目录的深度未知。
我想将所有*.log文件放入同一输出目录中,基本名称以子目录路径为前缀(替换/#)。

例子:

/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

我怎样才能更优雅地做到这一点?

答案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 

答案2

通过使用\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打印\0- 分隔的文件路径(%P意味着没有 的find目录$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

答案3

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

  • cd 到项目目录
  • 找到所有日志文件
  • tar 的日志文件列表到标准输出
  • cd 到输出目录
  • 解压标准输入

相关内容