1つのコマンドラインで引数としていくつかのファイルを取り込むプログラムがあります。ディレクトリ内のすべてのファイルを時間の逆順にリストして呼び出します。
例えば:
ディレクトリに次のファイルを時間の逆順で持っています
$ ls -tr
Introduction.pdf 'Object-Oriented Data Model.pdf'
プログラムを簡単に実行でき、
myprogram Introduction.pdf 'Object-Oriented Data Model.pdf'
別のコマンドでファイル一覧を表示したいのですが。 1つのファイル名にスペースがあるため、これは機能しません。
myprogram $(ls -tr)
ls
の出力を解析することはお勧めしません。 find
が役立つかどうかはわかりません。
その後、私は何ができますか?
ありがとう。
GNUユーティリティの合理的な最新バージョンがある場合、それらにNULLで終了するデータを処理させることができます。これにより、空白や改行の影響を受けないパイプラインを構築できますデータ自体。
私のテストツールは/tmp/args
というクイックスクリプトです。
#!/bin/bash
echo "This is args with $# value(s)"
for f in "$@"; do echo "> $f <"; done
これは、コマンドラインで一連のファイル名をフィードする方法です。ファイル名の最終変更時刻順にソートされています。
find -type f -printf "%T@ %p\0" | sort -zn | sed -z 's/^[0-9.]* //' | xargs -0 /tmp/args
find
コマンドは、各ファイル/パス名の前に、最後に変更された日付/時刻の小数秒での表現を付けます。これはsort
によって処理され、最低(最も古い)から最高(最新)の順に並べられます。 sed
は、ソートに使用した先の番号を取り除き、結果のファイル名のセットがxargs
に渡されます。ファイル名から先頭の%p
を省略したい場合は、%P
を./
に置き換えます。
データの例
# "c d" contains a space; "e f" contains a newline; "h" has leading whitespace
touch a 'e
f' g ' h ' 'c d' b
結果の例
This is args with 6 value(s)
> ./a <
> ./e
f <
> ./g <
> ./ h <
> ./c d <
> ./b <
Bash まだ変更時間でファイルをソートすることは簡単ではありません なので、ここに必須のzshベースの答えがあります。その機能を使用するために、ログインシェルとしてzshに切り替える必要はありません。
ここでは、1つまたは2つの引数を受け取るラッパー関数を設定します。最初の引数は実行するプログラムです(例:myprogram
); 2番目のオプションの引数は、プログラムに渡すファイルを含むディレクトリです。 2番目の引数を指定しない場合、デフォルトで現在のディレクトリが使用されます。
zeio() {
# Zsh-based Execute with files In Order
[ -d "${2:-.}" ] || return
zsh -c "$1 \"${2:-.}\"/*(.om)"
}
もちろん、好きな名前を付けてください。 2番目の引数(ここでも、デフォルトで現在のディレクトリである.
にデフォルト設定されています)の健全性チェックを行った後、プログラムといくつかの初期引数(引数#1)を含む単一引用符で囲まれた文字列でzshを呼び出します。ディレクトリ(引数#2)—デフォルトは.
です—末尾の括弧に2つの "glob qualifiers" を含むワイルドカード/ glob拡張を使用します:
.
-通常のファイルである必要があります(ディレクトリやシンボリックリンクなどは不可)om
-o
rder(ソート)結果のリストを変更時間順に、最新のものからここで実際の作業をすべて行うのは、そのom
グロブ修飾子です。
ここにいくつかのサンプル実行があります。 myprog
は、受け取った引数を順番に示す単純なシェルスクリプトです。
#!/bin/sh
for arg do
printf 'Arg: ->%s<-\n' "$arg"
done
go.sh
は、関数を保存したファイルです。残りのディレクトリ構造は次のとおりです。
$ tree .
.
├── dir1
│ ├── 203142
│ ├── 203143
│ └── 203144
├── dir3
│ ├── first\012filename
│ ├── this is 3rd
│ └── this is second
├── dir two
│ ├── 203225
│ ├── 203226
│ └── 203227
├── go.sh
└── myprog
...ここで、リストされたシーケンスの各サブディレクトリに3つのファイルのセットを作成しました。関数を実行すると、同じ順序で表示されることを期待しています。 dir3の下の最初のファイル名には改行があり、tree
と\012
で表されます。結果は次のとおりです。
$ zeio ./myprog
Arg: ->./myprog<-
Arg: ->./go.sh<-
$ zeio ./myprog dir1
Arg: ->dir1/203142<-
Arg: ->dir1/203143<-
Arg: ->dir1/203144<-
$ zeio ./myprog "dir two"
Arg: ->dir two/203225<-
Arg: ->dir two/203226<-
Arg: ->dir two/203227<-
$ zeio ./myprog dir3
Arg: ->dir3/first
filename<-
Arg: ->dir3/this is second<-
Arg: ->dir3/this is 3rd<-
(IFS=$'\n'; set -f; your_program $(ls -tr))
ファイル名に改行が含まれていないと仮定します。
例:
% touch 'a b'
% touch 'c d'
% touch '*'
% (IFS=$'\n'; set -f; printf '%s\n' $(ls -tr))
e f
a b
c d
*
$'...'
文字列をサポートしない標準シェルのバリアント:
(IFS='
' ; set -f; your_program $(ls -tr))
単純なpythonラッパー。改行を含むファイル名でも機能します。使用方法はthis_wrapper your_program *
です。
#! /usr/bin/python
import os
import sys
sys.argv[2:] = sorted(sys.argv[2:], key=os.path.getmtime)
os.execvp(sys.argv[1], sys.argv[1:])