少しの操作の後、私は幸せに実行できるコマンドを含むファイルを得ました。
入力ファイル(ファイル名はinp2.txt):
"02 - Beautiful Emptiness.mp3"
"02 - Come. mp3"
"02 - Go For It.mp3"
パスワード:
#!/bin/bash
exec 4<inp2.txt # opening file via descriptor
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
$LINE # execute command
done
編集する:申し訳ありません。理解する上で重要ではないと考えられる重要なコード部分を省略しました。完全なコード:
#!/bin/bash
IFS='
'
declare LINE
declare BUF
declare a
a=1
rm inp2.txt # delete previous version of file
exec 3< inp.txt # open descriptor for a file()content of it is written above
while read LINE <&3; do # read it
printf "mv ""$LINE"" %s\n" """$a"".mp3" >> inp2.txt
# form a command and output it to the file, just to make sure that I got a command that I really want
let "a++" # increment number that will be a part of new unique name
done
exec 4<inp2.txt #open again descriptor with ready commands
while read LINE <&4; do
printf "%s\n" "$LINE" # check again
$LINE # here it should be executed, but I get mistakes that is pointed down
done
exit 0
出力:
コマンドは正しいと思いますが、何かが間違っていて、正確に何が間違っているのかわかりません。
答え1
公開したスクリプト、データファイル、および出力が一致しません。スクリプトやデータファイルはすべて含まれていませんが、mv
スクリーンショットは含まれています。また、あなたのスクリーンショットには、あなたが投稿したスクリプトにない28行が記載されています。一貫性のない情報を提供すると、問題を正確に把握することは困難です。
つまり、2つのうちの1つを実行しようとしていますが、どちらも目的に応じて機能しません。
入力ファイルに次の行が含まれている場合
mv "02 - Beautiful Emptiness.mp3" 1.mp3
まあ、それは実際にはシェルスクリプトです。 1行ずつ読み込むのではなく、シェルスクリプトとして実行してください。
rm -rf ~
そのファイルを含むファイル内のすべてのエントリを実行するので、このファイルが信頼できることを確認してください。. inp2.sh
入力ファイルに次の行が含まれている場合
"02 - Beautiful Emptiness.mp3"
すると、読み方がうまくいきません。
read LINE
以下を行います。- 一行を読んでください。
- 行がバックスラッシュで終わったら、バックスラッシュを削除して別の行を読みます(
\
aで終わらない行を読むまで繰り返し)。 - すべてのバックスラッシュ+文字シーケンスを2番目の文字にのみ置き換えます。
LINE
改行を除いて読み取った行の接続に設定されます。
シェルが command を実行するときに
$LINE
引用符の外側の変数置換を表示するときに常に実行する操作を実行します。- 変数の値をスペースを含む各位置の単語のリストに分割します(デフォルトはと仮定します
IFS
)。 - 各単語をグローバルパターンとして扱い、1つ以上のファイルと一致する場合は拡張します。
役に立たないと思いますか?これは。ここには引用符の内容がないことに注意してください。引用符は、シェル拡張規則の一部ではなく、シェル構文の一部です。
inp2.txt
1行に1つずつファイル名のリストを含める必要があります。バラより"IFS=;"代わりに「IFS = Read」が頻繁に使用されるのはなぜですか?ファイルから行リストを読む方法を学びます。あなたは次のようなものが欲しいでしょう
i=1
while IFS= read -r source; do
dir=$(dirname -- "$source")
ext=
case "${source##*/}" in
*.*) ext=.${source##*.};;
esac
mv -- "$source" "$dir/$i$ext"
done <inp2.txt
完全性を期すためにもう一つの可能性について言及しますが、退屈したいように見えることができなくなるので、お勧めしません。このようなファイル
"02 - Beautiful Emptiness.mp3" "02 - Come. mp3" foo\ bar.mp3
その後、コマンドを介して読み取ることができますxargs
。入力はxargs
、スペースで区切られた要素のリストで、単一引用符で囲まれたリテラル(スペースを含めることができます)、二重引用符で囲まれたリテラル(スペースを含めることができます)、またはバックスラッシュエスケープ文字のないリテラルです。テキスト(\
次の文字引用)。このxargs
構文は、シェルが認識できる構文とは異なります。
答え2
一見すると引用に問題があるようです。
「コマンドの実行」行でそれを引用符で囲むと、そのコマンドはいくつかの追加パラメータを持つコマンドでは"$LINE"
なく単一のコマンドとして扱われます。mv
したがって、まずその行から引用符を削除する必要があります。
また、パスに問題があります。ファイル名にスペースがあるようです。したがって、inp2.txtファイルを変更して、スペースを含むパス/ファイル名の周りに引用符を追加するか、スペースをエスケープする必要があります。
また、スクリプトの上部に以下を追加してみることもできます。
IFS='
'
はい、2行目はその行の一重引用符です。これにより、スクリプトでスペースを処理する方法が変更されます。
スクリプトは次のとおりです。
#!/bin/bash
IFS='
'
exec 4<inp2.txt # opening file via descriptor
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
$LINE # execute command
done
答え3
このバージョンは、コマンドラインを作成し、それをbashに入力して実行するように機能します。
#! /bin/bash
i=1
while read LINE ; do
# strip off any leading or trailing double-quotes.
# script now works whether input quotes the filenames or not.
LINE=$(echo "$LINE" | sed -r -e 's/^"|"$//g')
[ -n "$LINE" ] && echo mv \"$LINE\" \"$i.mp3\"
i=$((i + 1))
done < inp2.txt | bash
注:スクリプトをパイロットテストするには、| bash
最後の行を削除またはに変更してください| cat
。これにより、次のような出力が生成されます。
mv "02 - Beautiful Emptiness.mp3" "1.mp3"
mv "02 - Come. mp3" "2.mp3"
mv "02 - Go For It.mp3" "3.mp3"
この[ -n "$LINE" ]
テストは入力から空白行をスキップします。私が作成したinp2.txtの最後に追加の空行があるので追加されました。
答え4
このようなことを試してみましたか?
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
comm="$LINE" # asssign command to a variable
$comm # execute command
done
bashを使えば私にとって効果的です。