findコマンドを実行するときに値をどのように設定しますか?

findコマンドを実行するときに値をどのように設定しますか?

長い一連の-execコマンドを実行しており、実行の開始時にタイムスタンプを抽出して後続のコマンドの値として使用しようとしています。可能ですか?それは次のとおりです。

find . -exec NOW=$(date +%s) {} \; -exec echo $NOW."$0" {} \;
find . -exec set NOW=$(date +%s) {} \; -exec echo $NOW."$0" {} \;
find . -exec export NOW=$(date +%s) {} \; -exec echo $NOW."$0" {} \;

これはうまくいきませんが、値を設定する代わりに$(date + % s)を使用すると、後続の各-execが時間とともに発生するため、タイムスタンプが一貫しなくなります。

私が望むのは、ファイルごとに異なるタイムスタンプを持つことです。たとえば、誰かの提案を変更すると、私の意図をよりよく表現することができます。

find . -exec sh -c '
    NOW=$(date +%s); for f in "$@"; do echo "$NOW  $f First Output"; sleep 3; echo "$NOW $f Second Output"; done
' find-sh {} +

このコマンドは私が望むことはしませんが、最初のファイルに対して操作を実行するのに遅れてタイムスタンプを変更しないでください。タイムスタンプとファイル名、スリープ3を出力し、ファイルに対して同じタイムスタンプを出力する必要があることを示します。次に、次のファイルに使用する新しいタイムスタンプを作成したいと思います。

答え1

-exec次のように1つだけ使用してくださいsh -c

find . -exec sh -c '
    NOW=$(date +%s);
    echo "$NOW $1 First Output";
    sleep 3;
    echo "$NOW $1 Second Output";
' find-sh {} \; 

あるいは、何らかの理由で接続されたsに固執するために一時ファイルを使用できますが、その一時ファイルを読むたびに次のものが-exec必要です。sh -c

find . \
  -exec sh -c 'date +%s > /tmp/now' \; \
  -exec sh -c 'echo "$(cat /tmp/now) $1 First Output"' find-sh {} \; \
  -exec sleep 3 \; \
  -exec sh -c 'echo "$(cat /tmp/now) $1 Second Output"' find-sh {} \;

-execシェルが実行する$(..)前にその部分を評価するため、以下は機能しませんfind

-exec echo "$(cat /tmp/now) {} First Output" \;

添付:

あなたはこれがどこから来たfind-shのか尋ねることができます-exec sh -c '...' find-sh {}これが答えです

答え2

NOW各ファイルにリセットします。つまり、~へサイクルfor:

find . -exec sh -c '
   for f do
      NOW=$(date +%s)
      echo "$NOW  $f First Output"
      sleep 3
      echo "$NOW $f Second Output"
   done
' find-sh {} +

答え3

何をしたいのかわかりませんが、$NOW各ファイルの処理中に各ファイルの値を現在の時代に更新したい場合は、その変数zsh$EPOCHSECONDSまたは$EPOCHREALTIMEナノ秒を望む場合)モジュールを使用できますzsh/datetime(または${(%):-%D{%s}}バンドを使用しない)zsh/datetime。あまり明確ではない):

find . -exec zsh -c '
  zmodload zsh/datetime
  typeset -F SECONDS # make it float
  for file do
    start_time=$EPOCHSECONDS SECONDS=0
    print -r $start_time processing $file

    processing $file

    end_time=$EPOCHSECONDS duration=$SECONDS
    print start=$start_time end=$end_time duration=$SECONDS
  done' zsh {} +

またはzshcan dofindの作業は再帰的グローブを使うことだからです。

#! /bin/zsh -

zmodload zsh/datetime
typeset -F SECONDS # make it float.

for file (./**/*(ND)) {
  start_time=$EPOCHSECONDS SECONDS=0
  print -r $start_time processing $file

  processing $file

  end_time=$EPOCHSECONDS duration=$SECONDS
  print start=$start_time end=$end_time duration=$SECONDS
}

bashシェルではstart_time=$EPOCHSECONDSwithと同等のものが得られますprintf -v start_time '%(%s)T'

関連情報