コマンドラインからファイルのリストを受け入れ、xargsを使用してすべてのファイルの日付付きコピー(basename_date.extension)を作成するにはどうすればよいですか?

コマンドラインからファイルのリストを受け入れ、xargsを使用してすべてのファイルの日付付きコピー(basename_date.extension)を作成するにはどうすればよいですか?

この問題を解決するために多くの時間を費やしましたここxargs呼び出しに頼らずに正しい出力を得ることができましたbash(このチュートリアルでは扱いません)。サブコールからbash正しい参照を取得するのに時間がかかりました。何らかの理由で変数にxargs保存し、再計算して新しい変数に保存する必要がありました。replace-strdate

編集:私はこれがrenameこの問題を解決するためにも使用できることを知っていますが、これは私がリンクしたチュートリアルでまだ扱っていません。

  • 明らかに、パラメータ拡張は= {}では機能しないため、replace-str「{}%%。*」を実行してファイル拡張子を取得できません。
  • 明らかに、コマンドで実行される子bashプロセス内で使用される場合、二重引用符で囲まれた変数もtodaynullになりますxargs

    # %<conversions> come from 'man 3 strftime'                                                                                                                  
    today=$( date "+%Y-%m-%d" )

    # make prefix date copy                                                                                                                                      
    #ls "$@" | xargs -I ^ cp ^ "${today}_^"                                                                                                                        

    #make suffix date copy                                                                                                                                                                                                                                                       
    echo "$@" | sed "s; ;\n;g" | xargs -I {} \
                          bash -cs 'var="{}"; td=$( date "+%Y-%m-%d" ); \
                                    echo "${var%%.*}_${td}.${var##*.}"'
    #prints basename_.bash i.e. without date
    echo "$@" | sed "s; ;\n;g" | xargs -I {} \
                          bash -cs 'var="{}"; \
                                    echo "${var%%.*}_${today}.${var##*.}"'

出力されます

    s1_2021-03-11.bash s2_2021-03-11.bash 

入力するとき

    ./myscript s1.bash s2.bash

編集:入力を繰り返すには:

    ./myscript file1.ext file2.ext file3.ext ... fileN.ext

実行後、ls次のファイルが存在する必要があります。

    file1_yyyy-mm-dd.ext ... fileN_yyyy-mm-dd.ext

可能であれば、ウェブサイトのチュートリアルでまだこの内容を扱っていないので、うまくいかないソリューションを探してみたいと思いますbash -c。だから、それが問題を解決しようとする意図なのか疑問です。また、パラメータ拡張がxargsと機能せず、他の日付変数が必要であるという混乱も理解したいと思います。

答え1

xargs/sed の GNU バージョンにアクセスできない場合は、xargs-safe ファイル名を引用する必要があります。

使用法:

 ./myscript   your list of files goes here
#!/bin/bash

# user defined function: qXargs
# backslashes all chars special to xargs:
# SPC/TAB/NL/double quotes, single quotes, and backslash.

qXargs() {
  printf '%s\n' "$1" |
  sed \
    -e "s:[\\'${IFS%?}\"]:\\\\&:g" \
    -e '$!s:$:\\:'  \
  ;
}

# loop over command-line arguments
# quote them to make xargs safe and
# break apart arg into head portion and
#'extension and slip in today's date

today=$(date +'%Y-%d-%m')

for arg
do
   src=$(qXargs "$arg")
  head=$(qXargs "${arg%.*}")
  tail=$(qXargs "${arg##*.}")
  printf '%s\n%s_%s.%s\n'  \
    "$src" \
    "$head" "$today" "$tail" ;
done | xargs -n 2 -t mv -f --

ユーティリティはGNUバージョンであると仮定します。

#!/bin/bash
### this is the ./myscript file
d=$(date +'%Y-%d-%m')
printf '%s\0' "$@" |
sed -Ez "p;s/(.*)(\..*)/\1$d\2/" |
xargs -r0 -n2 -t mv -f --

メモ:

  • xargs置換文字列{}から拡張を取得できないという混乱は、bcoz{}がxargsに引数に置き換えるように促すプレースホルダーにすぎないということです。したがって、xargsコマンドを解析すると、シェルはそれを見ることができません。

関連情報