私はシノロジーNASを使用しています。削除するファイルのリストがあり、ファイル名にフルパスが一覧表示されますMyfiles.txt
。ファイルには約3000行があり、次のようになります。
"/volume2/NBU/Downloads/AA_To be seen/Life.Itself.2018.1080p.WEB-DL.DD5.1.H264-FGT/RARBG.txt"
"/volume2/nbU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E16.High.Stakes.Hip.Hop.WEBRip.x264-ION10.mp4"
"/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4"
次のスクリプトを使用しています(ls
後で交換するようにテストされていますrm -f
)。
#!/bin/bash
while IFS="" read -r p;
do
ls "$p"
done < "Myfiles.txt"
残念ながら、スクリプトを実行すると、ループごとに次のメッセージでエラーが発生します。
ls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Life.Itself.2018.1080p.WEB-DL.DD5.1.H264-FGT/RARBG.txt": No such file or directory
ls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E16.High.Stakes.Hip.Hop.WEBRip.x264-ION10.mp4": No such file or directory
ls: cannot access "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4": No such file or directory
ただし、コマンドラインから直接その行を実行すると機能します。たとえば、
ll "/volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4"
出力は次のとおりです。
-rwxrwxrwx+ 1 Pansysadmin users 275337817 Dec 15 2018 /volume2/NBU/Downloads/AA_To be seen/Find.Me.in.Paris.S01.WEBRip.x264-ION10/Find.Me.in.Paris.S01E14.Time.to.Face.the.Music.WEBRip.x264-ION10.mp4
実行スクリプトを使用してもsudo
同じエラーが発生します。
私は何を見落としていますか?
答え1
引用符はファイル名の一部ではありません。のようなファイルを削除しようとしていますが、"file.txt"
ファイル名は実際にはですfile.txt
。
touch "file.txt" # shell uses quotes; name is simply file.txt
ls "file.txt" # quotes used by shell; success
ls file.txt # no quotes; success
ls '"file.txt"' # outer quotes used by shell to treat word-with-quotes as literal; failure
ファイル名が正しく(つまり、ファイル名の周りに二重引用符がないように)、ファイル名を変更するか、ループを変更してデータの誤った部分を削除してください。
試してみたばかりのコメントを見ましたsudo
。sudo
なぜ必要なのかまず理解しないで、それに頼らないでください。 (ここでは必要ありません。)そうしないと、ある日システムが提供しようとした保護機能を誤ってバイパスし、システムが損傷する可能性があります。
答え2
大きくするエマ・ルーオの答え、
シェルでコマンドを実行すると、コマンドラインで多くの処理と解釈が実行されます。たとえば、
- 入力したら
シェルはとのls foo bar
ls
2つの引数で実行されます。しかし、入力するとfoo
bar
シェルはls "foo bar"
ls
1つの引数で実行されますfoo bar
。 - 入力したら
シェルは、などrm north*
rm
のような多くのパラメータで実行されますnorth1
。しかし、入力するとnorth42
northwest
シェルはrm "north*"
rm
1つの引数で実行されますnorth*
。 - 入力したら
シェルは名前付きファイルを生成し、echo Math tells us that 5 > 4.
4.
そのファイルに内容を書き込みます。Math tells us that 5
など。
- 入力したら
read
コマンドが入力を読み取るときは処理しません。特に、入力行に、などのread
特殊文字が含まれている場合、その文字のみが変数に入力されます。スペースとタブは通常、まだ特別な意味を持っていますが、を使用して抑制することができます。バックスラッシュ()は通常まだ特別な意味を持ちますが、成功を使用して抑制することができます。開始と終了に設定されたファイル名にも同様です。*
>
"
p
IFS=
\
read -r
p
"
変数値の拡張は、シェルが実行する最後の操作の1つです。たとえば、次の操作を実行できます。
statement="Math tells us that 5 > 4." echo $statement
シェルは変数の内容の文字を
Math tells us that 5 > 4.
確認しないので(ターミナルに)書き込みます。statement
>
注:上記は悪い例です。一般的に言えば、次のように話す必要があります。
echo "$statement"
つまり、引用符があります。
だからあなたが言うとき
ls "$p"
シェルは
ls
引用符文字を含む引数で実行されます。これは本質的に同じです。ls '"/volume2/NBU/Downloads/AA_To be seen/Life.Itself … H264-FGT/RARBG.txt"'
(引用符内の引用符に注意してください)、実際のファイル名には引用符は含まれていません。