web-dev-qa-db-ja.com

`find`と` rename` –そのようなファイルやディレクトリはありません

サブディレクトリのファイル名のドットを削除したい。 renamefindを使用します。

 find . -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g' {} \;

コマンドfindは単独で機能します。コマンドrenameは単独で機能します。しかし、両方を一緒に使用すると、エラーが発生します。

No such file or directory 

それらを一緒に機能させる方法は?


私はこれをテストしましたが、機能しません:

mkdir test
cd test
mkdir f1
cd f1
touch {1..20}-file.with.dot.avi
cd ..
cp -r  f1/ f2
cd ..
find . -type f -name '*.avi' -exec  rename   's/\.(?=[^.]*\.)/ /g' "{}" \;

私はこれをテストしますが、動作しません

mkdir test
cd test
mkdir f1
cd f1
touch {1..20}-file.with.dot.avi
cd ..
cp -r  f1/ f2
cd ..
find . -type f -name '*.avi' -exec  rename   's/\.(?=[^.]*\.)/ /g' "{}" \;
1
Linquant

多くのrenamesがあります 。 OPのrenameはPerlrenameprenameと呼ばれることもあります)のようです。一般に、renamePerl renameを実行する場合と実行しない場合があります


エラーは次のようなものです。

_Can't rename ./test/f1/1-file.with.dot.avi  /test/f1/1-file with dot.avi: No such file or directory
_

ターゲットパスが意味をなさないことに注意してください。絶対的に見えますが、実際には_/_で始まりません。スペース文字で始まります。これは、先頭のドット(_._)がスペース文字に置き換えられたためです。ディレクトリ_<space>/test/f1/_はなく、renameはそれを作成しないため、_No such file or directory_。

findは、ユーザーが指定したパスの1つでパス名を開始する必要があり、パスとして_._を指定したため、ドットがありました。

いくつかの解決策があります:

  • 開始パスとして_._を使用しないでください。例えば。:

    _find "$PWD" -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g' {} \;
    _

    ディレクトリ名(_$PWD_が展開されるディレクトリまたはその下のディレクトリ)にドットがある場合は、同じ問題が発生する可能性が高いことに注意してください。

  • 欠落しているドットを再度追加します。

    _find . -type f -name '*.avi' -exec rename 's/\.(?=[^.]*\.)/ /g; s/^ /./' {} \;
    _

    これは一般的な解決策ではありません。繰り返しますが、パス名に_._のディレクトリコンポーネントが含まれている場合は、問題が発生する可能性があります。

  • findが_-execdir_をサポートしている場合は、それを使用してください。結果のパス名は_./1-file.with.dot.avi_のようになり、ディレクトリ名のドットは無関係になります。それでも、この主要なドットに対処する必要があります。例:

    _# re-adding dot like in the above approach
    find . -type f -name '*.avi' -execdir rename 's/\.(?=[^.]*\.)/ /g; s/^ /./' {} \;
    # or stripping ./ first
    find . -type f -name '*.avi' -execdir rename 's|^\./||; s/\.(?=[^.]*\.)/ /g' {} \;
    _

    利用できない場所で_-execdir_をエミュレートするPOSIXソリューションでは、シェルを実行する必要があります。可能なアプローチ:

    _find . -type f -name '*.avi' -exec sh -c '
       cd "$(dirname "$2")" && rename "$1" "$(basename "$2")"
    ' find-sh 's/\.(?=[^.]*\.)/ /g' {} \;
    _

    ノート:

    • rename自体はPOSIXツールではありません。
    • s/\.(?=[^.]*\.)/ /gを別の引数としてshに渡すことを選択しました。これは、単一引用符で囲まれたシェルコードに埋め込んで、引用符を適切にネストすることを心配するのではありません。
  • 式を改善して、ディレクトリコンポーネント(先頭のドットを含む)を変更せず、ファイル名(パス名の最後の_/_の後の文字列)のみを変更します。私はこれを助けるために正規表現で十分ではありません。

0