1つのフォルダに複数のファイルがあります。特定の順序でリストされたファイル名(拡張子なし)を含むcsvファイルもあります。ファイル名の先頭にテキストファイルリストの場所を含むようにフォルダのファイル名を変更したいと思います。
つまり、私のフォルダには次のものが含まれます。
aaa.txt, bbb.txt, ccc.txt
ファイル名.csvには次のものが含まれます。
ccc
aaa
bbb
私が得たいものは:
1_ccc.txt, 2_aaa.txt 3_bbb.txt
Bashでこれを行うことはできますか?
答え1
for i in *.txt
do line=$(grep -nx -m 1 -- "${i%%.*}" filename.csv | cut -f 1 -d ':')
name=${line}_${i}
mv -- "$i" "$name"
done
説明する
"${i%%.*}"
: Kusalanandaが提案したように値を取得し、$i
値の尾からパターンを削除します(追加情報.*
パラメータ拡張)
grep -nF --
-x
全行と一致-m 1
1つの一致する行の後にファイルの読み取りを停止します(grep
ファイルが非常に長い場合はすべての行を読み取るのを防ぐため)。--
オプションの終わりを示すために使用されます(詳細- シェルから)-n
次の形式で、行自体の代わりに行番号を返します。2:aaa 3:bbb 1:ccc
cut -f 1 -d ':'
:
上記の結果から区切り文字を含むフィールド1を抽出します。
答え2
awkもオプションであり、名前のスペースも処理できます。
file='filename.csv'
find_path='/home/kali/test/'
extension='.txt'
awk -v find_path=$find_path -v extension=$extension \
'/^$/{NR=--NR; next} \
/^.+/ {print "mv -f " "\"" find_path $0 extension "\" " \
"\"" find_path NR "_" $0 extension "\"" \
}' $file | sh
答え3
ファイル名のプレフィックスがCSVファイルの文字列であり、ファイル名に.txt
ファイル名のサフィックスがあり、他に何もないすべてのファイルの名前を変更したいとします。
#!/bin/sh
suffix=txt
n=0
while IFS= read -r prefix; do
n=$(( n + 1 ))
name=$prefix.$suffix
[ ! -e "$name" ] && [ ! -L "$name" ] && continue
mv -- "$name" "${n}_$name"
done <filename.csv
prefix
while
これはループが繰り返されるたびにCSVから1行を変数として読み取り、ファイル名を(静的文字列)$prefix.$suffix
$suffix
txt
${n}_$prefix.$suffix
n
mv
このコマンドは、ソースファイルが存在する場合にのみ実行されます。
名前の競合のテストはありません。