findで見つけたファイルを上書きしますか?

findで見つけたファイルを上書きしますか?

ファイルのリストがあります

-rw-rw-r-- 1 t t 24813 Oct 23  2002 fig8_21.gif
-rw-rw-r-- 1 t t  2259 Oct 23  2002 fig8_21t.gif
-rw-rw-r-- 1 t t 35331 Oct 23  2002 fig8_23.gif
-rw-rw-r-- 1 t t  2610 Oct 23  2002 fig8_23t.gif
-rw-rw-r-- 1 t t 19970 Oct 23  2002 fig8_24.gif
-rw-rw-r-- 1 t t  2019 Oct 23  2002 fig8_24t.gif
-rw-rw-r-- 1 t t 54623 Oct 23  2002 fig8_3.gif
-rw-rw-r-- 1 t t  3657 Oct 23  2002 fig8_3t.gif
-rw-rw-r-- 1 t t 35861 Oct 23  2002 fig8_4.gif
-rw-rw-r-- 1 t t  2344 Oct 23  2002 fig8_4t.gif

たとえば、コピーして上書きを<...>t.gif使用して上書きしたいと思います。<...>.giffig8_4.giffig8_4t.gif

私は<...>t.gifこれらのファイルを見つけることから始めますfind . -regex ".*t\.gif"。次に、ファイル名の削除を使用したいのですが、basename次の警告が表示されるのはなぜですか?

$ find .  -regex ".*t\.gif" -execdir basename {} \;  
find: The relative path `~/program_files/internet/SSH_tunneling/' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find.  Please remove that entry from $PATH

$ find .  -regex ".*t\.gif" | xargs basename 
basename: extra operand ‘./f10_1t.gif’

ミッションをどのように進めますか?

使用してはいけませんかfind

答え1

はい、可能です。 1つのアプローチは次のとおりです。

cd /den/of/gifs && \
for f in ./*t.gif; do
    mv -- "${f%%t.gif}.gif" "$f"
done

最も長い一致文字列を削除するための${var%%pattern}標準/POSIX構文。sh模様年末から始まります$var

答え2

より小さく高速にするには、次のものを使用できますparallel

parallel mv {} {.}t.gif  :::: <(find . -regex '.+[0-9].gif')

after式は::::パラメータを提供しますparallel。その後、このパラメータを使用してください{}{.}ファイル拡張子のないパラメータを示します。そのため、この例で{}は がないファイルのファイル名になります。たとえば。tfig8_4.gif{.}fig8_4

答え3

findsum を引き続き使用するには、basename次のようにします。

find . -name "*.gif" ! -name "*t.gif" -execdir sh -c '
  cp -- "$0" "$(basename "$0" .gif)t.gif"' {} \;

パフォーマンスとリソースの観点から見ると、これは最善の選択ではありません。

答え4

あなたのエラーについて:

find: 相対パス '~/program_files/internet/SSH_tunneling/' は PATH 環境変数に含まれており、 find の -execdir 操作で使用するのは安全ではありません。 $PATH からこのエントリを削除します。

あなた~/program_files/internet/SSH_tunneling/$PATH文字通り~。もちろんいいえあなたの意味メインディレクトリ。代わりに、次の意味があります。相対パス ~/program_files/internet/SSH_tunneling/つまり、現在のディレクトリ内のディレクトリ内にありますSSH_tunnelinginternetprogram_files~

-execdirコマンドを実行したいディレクトリに$PATH移動する相対ディレクトリを好まないでください。chdir()たとえば、ディレクトリツリーから降順に降りている間にディレクトリも含むfindファイルgifが見つかっている場合は、最終的に実行できます。./some-dir~./some-dir/~/program_files/internet/SSH_tunneling/basenameそれ basename

以下があるかもしれません。

PATH="~/program_files/internet/SSH_tunneling/"

あなたの場合は、次のようにする~/.bash*必要があります。

PATH=~/program_files/internet/SSH_tunneling/

または

PATH="$HOME/program_files/internet/SSH_tunneling"
 $ find .  -regex ".*t\.gif" | xargs basename 
 basename: extra operand ‘./f10_1t.gif’

xargsbasenameできるだけ多くのパラメータを使用して実行されます。basename最大2つのパラメータが必要です。最初のパラメータはパスで、2番目のパラメータはモードです。したがって、あなたの命令は意味がありません。

また、デフォルトxargsでは、findリストは入力時にスペース(ロケールや実装に応じてスペース、タブなどが可能)と改行(すべてファイル名に表示される場合があります)に区切る必要があります。そして引用符は特別に扱われます。これはフォーマット出力プロセスではありませんfind

find次のように出力されます。

./path/to/picture from "The End of the World".gif

これは、xargsの3つの異なるパラメータとして理解されます。予想される形式ではパターンが出力されません。ここでは次のようになります。./path/to/picturefromThe End of the World.giffindxargs

./path/to/picture\ from\ \"The\ End\ of\ the\ World\".gif

または

'./path/to/picture from "The End of the World".gif'

一部の実装では、スペース/改行+引用符の代わりにNUL区切りリストを処理するxargsオプションがサポートされており、一部の実装にはその形式でファイル名を出力する述語があります(そうでない場合は代わりに使用できます)。-0find-print0-exec printf '%s\0' {} +

だからこんな感じ:

find .  -name "*t.gif" -print0 | xargs -r0 -I {} basename {} t.gif

これは全体的な目標に大きな助けにはなりません。代わりに、次のようなことをしたいと思います。

find . -name '*t.gif' -type f -exec sh -c '
  for f do
    cp "${f%t.gif}.gif" "$f"
  done' sh {} +

または以下を使用してzsh

autoload zmv # if not already in ~/.zshrc
zmv -C '(**/)(*)t.gif(#qD.)' '$1$2.gif'

関連情報