シンボリックリンクを表示せずにすべてのコンテンツ(ファイルとサブディレクトリ)を一覧表示したいディレクトリがあります。 LinuxではGNUユーティリティを使用しています。ls
バージョンは8.13です。
例:
完全なディレクトリリスト:
~/test$ ls -Gg
total 12
drwxrwxr-x 2 4096 Jul 9 10:29 dir1
drwxrwxr-x 2 4096 Jul 9 10:29 dir2
drwxrwxr-x 2 4096 Jul 9 10:29 dir3
-rw-rw-r-- 1 0 Jul 9 10:29 file1
-rw-rw-r-- 1 0 Jul 9 10:29 file2
lrwxrwxrwx 1 5 Jul 9 10:29 link1 -> link1
lrwxrwxrwx 1 5 Jul 9 10:30 link2 -> link2
欲しいもの
~/test$ ls -somthing (or bash hack)
total 12
dir1 dir2 dir3 file1 file2
注:私の主な動機は、シンボリックリンクをたどらずに再帰的なgrep(GNU grep 2.10)を実行することです。
述べられた質問のためにあなたは使うことができます find
:
find . -mindepth 1 ! -type l
現在のディレクトリまたはシンボリックリンクではないサブディレクトリにあるすべてのファイルとディレクトリをリストします。
mindepth 1
は、.
の現在のディレクトリエントリをスキップするだけです。その本質は、「シンボリックリンクであること」を意味する-type l
と、次のテストの否定を意味する!
の組み合わせです。これらを組み合わせると、シンボリックリンクではないすべてのファイルに一致します。これはすべてのファイルとディレクトリを再帰的にリストしますが、シンボリックリンクはリストしません。
(ディレクトリではなく)通常のファイルだけが必要な場合:
find . -type f
このディレクトリの直接の子だけを含め、他のすべてを再帰的に含めないようにするには:
find . -mindepth 1 -maxdepth 1
これらの(およびその他の)テストを組み合わせて、必要なファイルのリストを取得できます。
使用しているテストに一致するすべてのファイルで特定のgrep
を実行するには、-exec
を使用します。
find . -type f -exec grep -H 'some pattern' '{}' +
'{}'
はファイルに置き換えられます。コマンドが完了したことをfind
に伝えるには、+
が必要です。オプション-H
は、単一の一致するファイルで実行された場合でもgrepにファイル名を表示するように強制します。
または、より簡単です:
ls -l | grep -v ^l
説明
ls -l
は、長い形式でリストすることを意味します。これを行うと、最初の文字列が各ファイルに関する情報を提供します。最初の文字は、各ファイルの種類を示します。シンボリックリンクの場合、l
が最初の文字です。
grep -v ^l
は、(-v
)で始まる行(^
)とl
をフィルターで除外することを意味します。
バージョン2.12以降、-r
オプションGNU= grepは、手動で指定しない限り、シンボリックリンクを逆参照しません。
-r、-recursive
コマンドライン上にある場合にのみ、シンボリックリンクをたどって、各ディレクトリの下のすべてのファイルを再帰的に読み取ります。これは-d recurseオプションと同等です。
-R、-dereference-recursive
各ディレクトリの下のすべてのファイルを再帰的に読み取ります。 -rとは異なり、すべてのシンボリックリンクをたどります。
Zshでは、これは glob qualifiers のおかげで簡単です。
grep -- PATTERN **/*(.)
パターン **/
はサブディレクトリを再帰的に走査します。グロブ修飾子.
は、通常のファイルへのマッチングを制限します。
Zshを使用しない場合は、find
を使用します( Michael Hornerの回答 を参照)。そしてこの特定のケースでは、GNU grepはあなたがやりたいことをすることができます(まさにgrep -r
します)—バージョン2.12以降、以前のバージョンはシンボリックリンクをたどりました。
これを行うには、$LS_COLORS
を使用できます。 ls
のバージョンがその変数を使用した色の指定をサポートしている場合は、ファイルタイプごとに出力を定義できます。これは組み込みの動作であり、非常に構成可能です。だから私はこれをデモするためにいくつかのファイルを作成しました:
for f in 9 8 7 6 5 4 3 2 1
do touch "${f}file" &&
ln -s ./"${f}file" ./"${f}filelink"
done
だから今私はやります:
LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \
ls -1 --color=always | cat
###OUTPUT###
1file
HERE_THERE_BE_A_LINK>>1filelink@
2file
HERE_THERE_BE_A_LINK>>2filelink@
3file
...
HERE_THERE_BE_A_LINK>>8filelink@
9file
...
そしてヌルもそこにあります...
LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \
ls -1 --color=always | sed -n l
1file$
$
$
\000HERE_THERE_BE_A_LINK>>\0001filelink@$
2file$
$
$
\000HERE_THERE_BE_A_LINK>>\0002filelink@$
3file$
...
すべてまたは任意のファイルタイプを指定できます。ただし、ls
にはターミナルエスケープ用のデフォルトのコンパイル値が組み込まれているため、1つのファイルタイプだけでこれを行うと、期待どおりにならない場合があります。 APIを単一のインターフェースとして扱う方がはるかに良いでしょう。現在の環境を解析して割り当てるdircolors
に設定されたデフォルトの簡単な小さな手段を次に示します。
LS_COLORS='rs=:no=//:lc=:rc=:ec=//:'$(
set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=/$fc//:"
done) ls -l --color=always | cat
私のホームディレクトリでの出力は次のようになります。
total 884
///-rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 /fi//1/
//drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 /di//Desktop//
//-rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 /fi//Terminology.log/
//-rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 /fi//new
file/
//lrwxrwxrwx 1 mikeserv mikeserv 10 Jul 11 04:18 /ln//new
file
link/ -> /fi//./new
file/
//-rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 /ex//script.sh/*
//-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//shot-2014-06-22_17-10-16.jpg/
//-rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 /fi//target.txt/
これをcat -A
でも実行できます。唯一の違いは、改行の$
が表示されることです。この構成では、ls --color=always
によって印刷できない文字が導入されることはなく、ここに表示されるものだけが表示されます。
ls
は、次のようにデフォルトのターミナルエスケープを挿入します。
${lc}${type_code}${rc}FILENAME${lc}${rs}${rc}
...ここで、$lc
のデフォルト値(コードの左側)、$rc
(コードの右側)、および$rs
(reset)は次のとおりです。
\033 - ESCAPE
m - END ESCAPE
0 - reset
...それぞれ。 ${type_code}
は、さまざまなfi
(通常のファイル-デフォルトは未設定)、di
(ディレクトリ)の代わりに使用されます、ln
(link)、および私が知っている他のすべてのファイルタイプ。 $no
(normal)もあり、これもデフォルトでは設定されておらず、各行の先頭の//
によって表されます。私の単純な小さなIFS=:
ブロックは、それぞれの構成可能変数の名前を独自の値として挿入し、スラッシュを1つまたは2つ追加するだけで機能します。ただし、\0
NULバイトでも同様です。
デフォルトでは、ls
は最初の出力$rs
の直前に1つの$lc
も挿入しますが、ここでは正確に表されていません。この場合、私は$ec
(終了コード)を指定しました。これは、すべての場合で$rs
の代わりに使用されます。指定されている場合、$rs
と$no
の間に余分な${type_code}
はありません。それ以外の場合と同様に、出力の開始時にファイル名andの直後に1回だけ表示されます-1行目の先頭にある1つの余分なスラッシュで確認できます。
これが私自身の$LS_COLORS
のスニペットです
printf %s "$LS_COLORS"
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:\
so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:\
or=40;31;01:su=37;41:sg=30;43:ca=30;41:\
tw=30;42:ow=34;42:st=37;44:ex=01;32:\
*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:...
そして、実際には、私の小さなシェルハックはおそらく過度に複雑です-これらの値を割り当てるための広く利用可能なインターフェイスがあります。詳細については、CLIでdircolors -p
を、info dircolors
を試してください。
ファイル名は任意の文字列で囲むことができます。必要に応じてコメントアウトできます。ファイル拡張子のみに基づいて同様の動作を指定できます。そのように指定できないことは実際には多くありません。
今、私はこれをすべて作り上げるだけではありません-偶然 ソースコード につまずいた後に私はそれについて学びました。
この特定の構成では、ls
は以下を発行します。
$no
-各レコードの開始時にレコードごとに1回
${type_code}
-各ファイル名の直前に1回、ファイルの種類の省略形を含め、常に$no
orと同じ行および->
の直後の7つの空白区切りフィールドの後に出現シンボリックリンクのターゲット。
$ec
-最初の行の直前に1回、その後各ファイル名の直後に1回のみ。
他のすべての値は空です。
以下はヌル区切りのls
ですが、今回はcat -A
を使用しますが、これがないと、前の例と同じようになります。
LS_COLORS='rs=:no=\0//:lc=:rc=:ec=\0//:'$(
set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=/$fc//\0:"
done) ls -l --color=always | cat -A
total 884$
^@//^@//-rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 /fi//^@1^@//$
^@//drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 /di//^@Desktop^@///$
^@//-rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 /fi//^@Terminology.log^@//$
^@//-rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 /fi//^@new$
file^@//$
^@//lrwxrwxrwx 1 mikeserv mikeserv 10 Jul 11 04:18 /ln//^@new$
file$
link^@// -> /fi//^@./new$
file^@//$
^@//-rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 /ex//^@script.sh^@//*$
^@//-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//^@shot-2014-06-22_17-10-16.jpg^@//$
^@//-rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 /fi//^@target.txt^@//$
そして、このような-l
ongリストからallシンボリックリンクを確実に削除するには、簡単な変更を加えることができます。
LS_COLORS='rs=:no=//:lc=:rc=:ec=/ :'$(
set -- di fi mh pi so do bd cd or su sg ca tw ow st ex
for fc do printf %s "$fc=$fc/:"
done)ln=///: ls -l --color=always | sed ':ln
\|///|{N;\|\n//|!bln};s|.*//||'
実行後の私の結果は次のようになります...
total 884
-rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 fi/1/
drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 di/Desktop/ /
-rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 fi/Terminology.log/
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 fi/new
file/
-rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 ex/script.sh/ *
-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 fi/shot-2014-06-22_17-10-16.jpg/
-rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 fi/target.txt/
上記のようなコマンドを使用する:
LSCOLORS=...$(...)fc1=///:fc2=///: ls ... | sed ...
...(ここで、fc1
とfc2
は、サブシェルでset --
の後にリストされているファイルタイプです)は、文字に関係なく、ls
出力から必要なファイルタイプの組み合わせを確実に削除するのに役立ちますファイル名に含まれている可能性があります。
上記の答えは以下につながります:
ls -1F | grep -i "/"
奇妙なことに、lsコマンドの1を残しても、リストは表示されます。