「ls」から「mv」にパイプを作成します。

「ls」から「mv」にパイプを作成します。

コマンドラインから小さなユーティリティを作成しようとしています。現在の作業ディレクトリに最近追加されたファイルを見つけ、引数として指定された名前をmv指定したいと思います。

私はこれでこれを達成しようとしてきました。 ls -tr | tail -n 1 | xargs -0 -J % mv % SQL_warning_2.png

...しかしbashは次のように報告します。

mv: rename Screenshot 2020-06-22 at 17.53.23.png
 to SQL_warning_2.png: No such file or directory

私はこれがxargsがfilename:の空白を別の引数として渡すことを意味すると思いますが、私が知っている限りこれにフラグはありませScreenshot 2020-06-22 at 17.53.23.png-print0ls

私の仮定の一部が間違っている場合は許してください。私はxargsについて非常に慣れていません。

答え1

ファイル名に改行文字が含まれていないと仮定しているようです(次をtail使用して1つを選択します)。

ls -tr | tail -n 1 | xargs -I % mv -- % SQL_warning_2.png

これによりユーティリティが一度呼び出され-I %ます。xargs各ライン%その行のテキストを読み、置き換えます。代わりに-J %スペースで行を分けてください。

$ echo 1 2 3 | xargs -J {} printf '"%s"\n' {}
"1"
"2"
"3"
$ echo 1 2 3 | xargs -I {} printf '"%s"\n' {}
"1 2 3"

現在のディレクトリで最後に変更されたファイルの名前を変更したいようです。シェルを使用すると、zsh次のことができます。

mv -- *(.om[1]) SQL_warning_2.png

mv最後に変更された一般ファイル名を最初の引数として使用します。om[1]mtime タイムスタンプに基づいて名前リストを並べ替え、最初の項目を選択する glob 修飾子です。前の点は通常のファイルのみを選択します(ディレクトリなどは選択しません)。

からbash

zsh -c 'mv -- *(.om[1]) SQL_warning_2.png'

答え2

私は次のようにします:

mv -- "$(ls -t|head -n1)" new_filename

(現在のディレクトリの最新のファイル名に改行文字が含まれていないとします。)

答え3

はい、使用するには-0標準xargs入力にNULで区切られたリストが必要です。ここでは、最後の改行の後に最新のファイルの名前部分を入力し、その後に改行を入力します(改行はファイル名lsの一部ではなくファイル名として追加されます)。

その入力には NUL がないため、xargs入力全体はmv改行文字を含む 1 つの引数として渡されます。したがって、最新のファイル名に改行文字が1つだけ含まれていて、ファイル名の最後の文字である場合にのみ機能します。 。

ここでは、改行で区切られたリストではなくNULで区切られたリストを出力することを確認する必要がありますが、これを行う実装はありませんlsls

xargsまたは、デフォルトの入力形式(除く-0)に戻す必要があります。ここでは、引数はxargsスペース(リストは実装と可能なロケールによって異なります)または改行で区切られ、およびと"..."'...'これら\の文字と互いをエスケープするために使用されます。同じシェル演算子を別の方法で引用できます。一部のxargs実装では入力をテキストとして解釈しようとしますが、ファイル名にはすべてのバイト値(NULを除く)を含めることができるため、/Cロケールでもこれを行う必要があります。

export LC_ALL=C
ls -td ./* | awk -v q="'" '
  {gsub(/"/, "\"\\\"\"")} # escape "
  NR == 1 {printf "\"%s", $0; next}
  /\// {exit} # a / means the start of the second file
  {printf "\"\\\n\"%s", $0} # escape newlines
  END {if (NR) print "\""}' |
  xargs -J % mv % newname

ご覧のとおり、xargs安定して使用することはお尻に痛みがあります。いくつかのxargs実装では、パラメータまたは入力ラインのサイズに対する制限は非常に低いです。これは-J移植不可能なBSD拡張であることに注意してください。

ラインベースのユーティリティを使用して任意のファイル名を処理することもls非常に困難です。

zsh@Kusalanandaが提案したように、それを使用して変更時間ごとにファイルリストを並べ替えることをお勧めします。

mv -- *(.om[1]) newname

では、bash次のこともできます。

IFS= read -rd / newest < <(ls -td ./*) && newest=${newest%.}
newest=${newest%?} # strip newline
[ -n "$newest" ] && mv "$newest" newname

(ksh93またはzshでも動作します)。前の方法と同様に、リスト内の2番目のファイルが始まる行を決定する機能をxargs使用します。./*

関連情報