私はスクリプトを書いたりコマンドを探したりする専門家ではありません(単に警告です)。私はすべてのmp3 Podcastを自分の携帯電話に移動できるフォルダに移動するスクリプトを作成しようとしています。
そのため、私が作成したスクリプトはすべてのmp3(パスが奇妙なファイルも含む)を移動する必要があります。以下のようにスクリプトを作成しましたが、意図したとおりに動作しているようですが、引き続き次のエラーが発生します。
find /home/jason/gPodder/ -name '*.mp3' -exec bash " cp '{}' /home/jason/gPodder/mp3/ " \;
Which returns:
bash: cp '/home/jason/gPodder/Downloads/The Documentary/TheDocumentary20170823-GoingGreenInTheOilState.mp3' /home/jason/gPodder/mp3/ : No such file or directory
しかし、上記のbash "コマンド"をコピーすると正常に動作します。スクリプトのエラーが何であるかを理解するのに役立ちます。
ありがとう
答え1
〜のように@Kusalanandaが言った。-c
、インラインスクリプトを使用する機能はありません。
{}
しかし、それにもかかわらず、任意のコマンドインジェクションの脆弱性(例'$(reboot)'.mp3
で呼び出されたファイル)になる可能性があるシェルコードには含めないでください。代わりに、インラインスクリプトのパラメータとして作成します(インラインスクリプトが実際に必要であると仮定し、これは単なるcp
例です)。
find ... -exec sh -c 'cp "$1" /home/jason/gPodder/mp3' sh {} \;
bash
(これだけのためにもする必要はありません。sh
意図も大丈夫です。)
または、より良い方法は、一度に複数の引数を渡すことですcp
。
find ... -exec sh -c 'cp "$@" /home/jason/gPodder/mp3' sh {} +
GNUを使用すると、cp
次のこともできます。
find ... -exec cp -t /home/jason/gPodder/mp3 {} +
答え2
必要以上に複雑にしないでください。
find /home/jason/gPodder/ -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \;
または多分
find /home/jason/gPodder/ -type f -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \;
一般ファイルのみが考慮されます。
同じ名前のファイルがターゲットフォルダにない場合にのみファイルをコピーしてください。一部のcp
実装では、このオプションをサポートするか、次のリダイレクトされた標準入力を-n
使用できます(ただし、ターゲットタイプがディレクトリの場合は機能しません)。次のようにしてください。-i
/dev/null
find /home/jason/gPodder/ -type f -name '*.mp3' \
! -execdir test -e /home/jason/gPodder/mp3/{} \; \
-exec cp {} /home/jason/gPodder/mp3/ \;
-execdir
POSIX標準の拡張ですが、多くの最新の実装でサポートされてfind
います。find
同様に実行されますが、-exec
見つかったコンテンツの親ディレクトリを作業ディレクトリとして使用してコマンドを実行します。また、フルパスではなく、{}
見つかった項目(file.mp3
または実装./file.mp3
に応じて)のデフォルト名になります。find
望むよりman find
。
このエラーはで発生しますbash "somecommand"
。bash
このように呼び出すと、一連のシェルコマンドではなくスクリプトファイルへのパスがbash
必要になり、somecommand
指定した名前のスクリプトが見つかりません。
一連のシェルコマンドを実行する必要がありますbash -c "somecommand"
。
ただし、この場合は-exec cp
上記の方法または次の方法を使用してください。Stefan Chazerasの答え。
答え3
他の人々は価格設定と実行の問題を指摘した。
find -execを使用する代わりに、xargsとcpのリストとパイプのリストを見つけることをお勧めします。 print0オプションを使用すると、ファイル名とディレクトリ名の「面白い」文字を防ぐのに役立ちます。
例えば
find sourcepath -name \*.mp3 -print0 \
| xargs -0 cp -t destinationpath
これの利点は、xargsがfindから複数のファイル名を収集して同時にcpに渡すので、各ファイルに対して1 cp呼び出しを実行する代わりに、各cpインスタンスが20または100個のファイルをコピーできることです。 xargsはcpコマンドラインに十分なファイル名を入力します。
xargs に -P n オプションを追加すると、複数の cp プロセスが並列に開始されます。
これは、ファイルが宛先mp3フォルダと同じファイルシステムにあると仮定します。 cpに-lを追加すると、ファイルをコピーするのではなく、ターゲットにハードリンクされます。
例えば
find sourcepath -name \*.mp3 -print0 \
| xargs -0 -P 5 \
cp -l -t destinationpath