"と*が付いたファイルを移動するとエラーが発生しました

Aug 22 2020

bashスクリプトでファイルを移動するのに問題があります。私はここで見つけた同じ問題についてさまざまな解決策を試してきましたが、うまくいくものが見つかりません。

私の最後の試みは追加shopt -s dotglob nullglobでしたが、それは何も解決しませんでした。

このテストでは、

jdir0="/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)"


mv -v "$jdir0/*" "$jdir0/subs/" &>> $debuglog

..そして私は得る:

mv: cannot stat '/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*': No such file or directory

しかし、はい、あります!

drwxrwx--- 1 root vboxsf   4096 Aug 22 07:06  ../
-rwxrwx--- 1 root vboxsf      0 Aug 21 17:19 'kallee.(222)..nnn.srt'*
-rwxrwx--- 1 root vboxsf 159363 Aug 21 17:26 'movie.test(2929).ismim.mp4'*
drwxrwx--- 1 root vboxsf      0 Aug 22 07:06  subs/

(名前が本当に奇妙な理由は、この関数の前に無効な文字を削除するためにテストしているためです)

更新:どうやら断続的なエラーが発生し、数日後にようやくサーバーの問題(ファイルが保存されている場所)までさかのぼることができました。どうやらこれらのエラーは、サーバーが保存/名前の変更を完了しておらず、スクリプトがサーバーに何か新しいことをするように要求した場合に発生したようです。たとえば、ファイルAの名前をBに変更し、サーバーが最初の要求を実行する前にBの名前をCに変更するように要求すると、サーバーは次のように言いました。Bは存在しません。もちろん、エラーコードが発生しました。

回答

7 StéphaneChazelas Aug 22 2020 at 05:44

*シェルのグロブ演算子です。そのように認識されるためには、引用符で囲まないでおく必要があります。引用された場合には、/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*文字通りに渡されるmvmv呼ばれる、そのファイルを移動しようとする*と、そのようなファイルがありません。

だからあなたは必要です:

mv -v -- "$jdir0"/* "$jdir0/subs/" >> "$debuglog" 2>&1

シェルを"$jdir0"/*呼び出す前に、一致するファイルのリストに展開しますmv

あなたはないではないしたいnullglobことは、その一致したファイルが存在しない状態であることを意味するであろうと、ここで"$jdir0"/*パターンを、mvただで呼び出されることになる-v--media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/subs/によって混乱構文エラーの原因となりますmv

failglobその場合、グロブが一致しないときにコマンドを中止する方が良いオプションかもしれませんが、その場合、bashコマンドが呼び出されるコンテキストに応じて一貫性のない方法で中止するため、スクリプトでそのオプションを使用するのは難しいことに注意してください。

dotglob グロブが隠しファイルと一致できるようにすることです。

ここで、グロブはタイプに関係なくファイルと一致することに注意してください¹。そのため、*上記も一致しsubsます。subsがディレクトリへのシンボリックリンクである場合、はmvそのsubsシンボリックリンクをそのディレクトリに移動しsubsます。これにより、ターゲットディレクトリがなくなるため、以降のすべての移動が失敗します。subsがプレーンなサブディレクトリの場合mv、ディレクトリをそれ自体に移動できないと文句を言う可能性があります。

したがって、代わりにそれを書きたいと思うかもしれません:

shopt -s extglob
mv -v -- "$jdir0"/!(subs) "$jdir0/subs/" >> "$debuglog" 2>&1

どこに!(pattern)あるん任意のファイル名に一致していることをkshの拡張グロブ演算子ではないと一致するpatternので、ここでは、任意のファイルを移動しますがsubs

また、bashシェルでは、非対話型シェルインスタンスでもリダイレクトのターゲットにある場合(bashがPOSIXモードの場合を除く)、パラメーター展開を引用符で囲む必要があることにも注意してください。


¹通常のファイル*(.)のみを移動するなど、bashとそのglob修飾子の代わりにzshを使用しない限り