Linuxでは、ユーザーによるls
出力の並べ替えにする方法はありますか?私が達成しようとしているのは、次のようなものです。
user _a file1
user _a file2
user _b another_file
user _c this_file
user _c that_file
user _d file3
このようなリストには、ファイルサイズ、権限なども含まれることを認識しています。私の主な関心事は、ユーザーによる並べ替えです。とても便利だろうね
これまでのところ、[ls -l | sort -k 3
を使用している場合]にファイル所有者が含まれている列3で並べ替えるls -l
が見つかりました[したがって、グループで並べ替えるsort -k 4
]。
[〜#〜] but [〜#〜]ファイル所有者が3行目にない場合はどうなりますか? 列の数に関係なくこれを達成するに別の方法はありますか?
更新:言及するのを忘れました私はBASHで働いていますそして、物事がより複雑にならないように、これからかなり長い間それに固執しようとします。
どちらが不可能かを知らずに、単一のls -l
出力から所有者名がどの列にあるかを判別します。各列のエントリをpasswd
ファイルと一致させようとすることもできますが、/etc/passwd
で見つかった名前しか含めることができないグループ列またはファイル名列の両方と一致しないという保証はありません。
ls
を使用する場合は、プログラムを2回実行できます。1回はls -l
として、もう1回はls -g
として実行できます。後者は所有者を削除するため、他の情報に基づいて行を照合することにより、指定なしで所有者名を判別できます。ただし、これはbashシェルスクリプトで実行したい演習ではありません。
zsh
を使用すると、並べ替え順序を定義して、次のようなグロブ修飾子で使用できます。
zmodload zsh/stat
uid() zstat -A REPLY +uid -- $REPLY
... *(no+uid)
(番号順の場合はn
、orderの場合はo
、uid
関数で注文する場合は+uid
)。アイデアは、$REPLY
のファイル名を受け取り、zsh
がソートする$REPLY
の何かを返す関数を持つことです。
したがって、たとえばGNU ls
:
ls -ldU -- *(no+uid)
GNUツールのみの場合、同等のものは次のようになります。
find . ! -name . -Prune -printf '%U\t%p\0' |
sort -zn |
tr '\0\n' '\n\0' |
cut -f2- |
tr '\0\n' '\n\0' |
xargs -r0 ls -ldU
ls
を解析しないでください :使用 stat
stat -c "%U %n" -- * | sort
OPは特定の移植性要件(Bashでの使用を除く)を規定しておらず、 lsの解析 が引き続き一般的なアプローチであるように思われるため、またstat
ベースのソリューションはファイル名の改行をうまく処理できないようです(とにかく、誰がファイル名に改行を入れますか?)、私は最もエレガントな解決策のために私自身の提案を投げかけるつもりです:
OPが実際にほぼ最良の答えを持っていたと思います。予期しない動作によるエイリアシングを防ぐために、エスケープする必要があります(これはBash固有のソリューションであることを忘れないでください)。
\ls -l | sort -k 3
18文字で、ls
とsort
のみが必要で、ループは必要ありません。エレガントで、理解しやすく、信頼性があります。
また、Olivierが彼の回答で指摘したように、sort
を、その列で始まる行全体ではなく、3番目の列のみに制限することが望ましい場合があります。
\ls -l | sort -k 3,3
3番目の列に所有者が含まれていないls -l
の実装、または他の回答で与えられたソリューションを壊さないこのソリューションを壊す方法を誰かが見つけた場合、この回答を撤回します。
1)どの列が名前であるかを判別します。
myls='ls -al'
echo '+' > /tmp/MYOWNFILE.$$ #so file will be of size 2, "+" and newline.
zeuser=$( $myls /tmp/MYOWNFILE.$$ | awk -v myname=$(whoami) '{ for (field=1;field<=NF;field++) { if ($field == myname) { print field ; break } } }' )
zesize=$( $myls /tmp/MYOWNFILE.$$ | awk '{ for (field=1;field<=NF;field++) { if ($field == 2) { print field ; break } } }' )
zename=$( $myls /tmp/MYOWNFILE.$$ | awk -v filename=/tmp/MYOWNFILE.$$ '{ for (field=1;field<=NF;field++) { if ($field == filename) { print field ; break } } }' )
rm /tmp/MYOWNFILE.$$
ユーザー名を示す列を変数zeuserに配置します
サイズを保持するzesize = column、およびファイル名を保持するzename = columnも決定します
Lsコマンドを変数に入れるので、列を決定する行は、後で使用される実際のコマンドを使用します(変更して、リストされている列を変更する場合)
2)並べ替えを使用してその列を並べ替えます。
$myls | sort -k${zeuser},${zeuser} #sort ONLY on column of usernames (see last example for bad alternative)
$myls | sort -k${zeuser},${zeuser} -k${zename},${zename} #sort on user, and then on filename
$myls | sort -k${zeuser},${zeuser} -k${zesize},${zesize}nr #sort on user,
# and then on size
#modifiers: 'n'=order Numerically (and not alphabetically),
# 'r'=Reverse order
$myls | sort -k${zeuser} #sort STARTING FROM user column, which is probably not what you want!
#indeed the next column is probably the group, then the size...
#It will be sorting in a not so usefull way (especially as the
# size will be sorted alphabetically instead of numerically)
これがあなたのためにそれをするべきである小さな1つのライナーです:
\ls -l | sort -k$(for i in {1..5}; do field=$(\ls -ld ~ | cut -d' ' -f$i); if [ x$field = x$(whoami) ]; then echo $i; break; fi; done)
ホームディレクトリで実行されたls -l
の各フィールドを、ユーザー名に一致するフィールドが見つかるまでウォークスルーし、その番号を-k
オプションに置き換えてsort
。
私はあまり専門家ではないので、これのいくつかはbashバージョンまたはGNU固有ですが、私のマシンでは正常に動作します。
1〜5を選択したのは、ユーザーを見つけるために必要な範囲であるためです。特にls -ld ~
の出力を毎回呼び出すのではなく文字列に保存した場合は、より多くの数値を使用できます。結果を配列に格納してそのように参照すると、さらに最適化できる可能性があります。しかし、これは頭のてっぺんから離れて、素早く汚いものでした。