作業ディレクトリがあります。/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
2つの別々のレコードとして作成します\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
- 標準入力の解凍