テキストファイルからファイルリストの名前を変更する

テキストファイルからファイルリストの名前を変更する

これらのファイルのリストを含むフォルダがあります。

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}"

関連情報