これらのファイルのリストを含むフォルダがあります。
lesson1.mp4
lesson2.mp4
lesson3.mp4
lesson4.mp4
"rename.txt"の内容に基づいてこのファイルの名前を変更しようとしています。
1. Introduction to the React Ecosystem Video
2. Video Babel, Webpack, and React
3. Solution - Props
4. Solution - .map and .filter
このスクリプトを実行しています。
for file in *.mp4;
do read line;
mv -v "${file}" "${line}";
done < rename.txt
これは私に望ましくない結果を与える
'lesson1.mp4' -> '1. Introduction to the React Ecosystem Video '
'lesson10.mp4' -> '2. Video Babel, Webpack, and React '
'lesson11.mp4' -> '3. Solution - Props '
'lesson12.mp4' -> '4. Solution - .map and .filter '
'lesson13.mp4' -> '5. Video Validating Components with PropTypes'
望ましい結果。
'lesson1.mp4' -> '1. Introduction to the React Ecosystem Video.mp4'
'lesson2.mp4' -> '2. Video Babel, Webpack, and React.mp4'
'lesson3.mp4' -> '3. Solution - Props.mp4'
'lesson4.mp4' -> '4. Solution - .map and .filter.mp4'
'lesson5.mp4' -> '5. Video Validating Components with PropTypes.mp4'
答え1
ワイルドカードの代わりにシェル拡張を使用できます。
for file in lesson{1..10}.mp4;do
read line
mv -v "${file}" "${line}"
done < rename.txt
エラーが発生しやすいように見えるかもしれませんが、これを行う必要があるファイルが多い場合は、ファイル名の数字が名前が変更されたファイルの行の先頭にある数字と一致することを確認できます。それは次のとおりです。
for file in *.mp4;do
num=$(echo "${file}" | sed -E 's/^lesson([0-9]+).mp4$/\1/')
line=$(grep -E "^ *${num}\." rename.txt)
mv -v "${file}" "${line}"
done
このように、ファイルの順序は重要ではなく、rename.txt
シェルグローバルファイル名の順序も重要ではありません。
答え2
この回答では、-v
オプションを使用してls
ファイルリストの正しい数値順序を保証します。各ファイル名はシェル位置引数に置かれます。各引数に完全なファイル名が含まれるようにするために、シェルの「内部フィールド区切り文字」を一時的に変更するので、最終ファイル名にスペースが含まれていても機能し続けます。最後に、私はスペースを含むファイル名が嫌いなので(そして同様の本能を開発する方が良いでしょう)、すべての埋め込みスペースを下線に変換します。このshift
コマンドは、単にすべての位置引数の値を前方にポップして、リストの$1
次の値を取得します。
oldifs="${IFS}"
IFS=$'\n'
set $(ls -v1 lesson*)
while read line ; do
mv "$1" "${line// /_}"
shift
done < rename.txt
IFS="${oldifs}"