シンボリックリンクを無視するディレクトリのlsコンテンツ


16

シンボリックリンクを表示せずに、すべてのコンテンツ(ファイルおよびサブディレクトリ)を一覧表示するディレクトリがあります。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)を実行することです。

回答:


28

記載されている質問には、次を使用できます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は、1つの一致するファイルで実行された場合でも、grepにファイル名を強制的に表示します。


パターンが見つかった魔女のファイルは表示されません。
TheMeaningfulEngineer 14

それはあなたが実行grepするものです(最後の段落を参照)。
マイケルホーマー14

私は私のために働きません。見つかったファイル名なしで、見つかったパターンを出力するだけです。
TheMeaningfulEngineer 14

2
を使用しgrep -Hている場合は(を参照man grep)、使用しgrep 'pat' '{}' /dev/null ';'ていない場合は複数のファイルがあると思わせるようにします。
マイケルホーマー14

1
+1つだけのファイルまたは最後に1つのファイルが残っている縮退の場合、その要件を満たすことができません。
マイケルホーマー14

16

または、より簡単です:

ls -l | grep -v ^l

説明

ls -lは、長い形式でリストすることを意味します。これを行うと、文字の最初の文字列は各ファイルに関する情報を提供します。最初の文字は、各ファイルのタイプを示します。シンボリックリンクの場合、an lが最初の文字です。

grep -v ^l(除外するための手段-v()で始まる行^l


これはうまく機能しますが、フォルダ名のみを取得する方法は?これを使用したいfor i in
ルカ

このコードを説明してもらえますか?
ABG

を省略-lすると、このソリューションは機能しないことに注意してくださいls。したがって、これは期待どおりに機能しませんls | grep -v ^l
。–スタムスター

@Lukaの出力をループしません。unix.stackexchange.comfind
questions / 321697を

1
@abg-説明を追加しました。それが役に立てば幸い。
ジェフ

7

バージョン2.12以降、-rGNU grep のオプションは、手動で指定しない限り、シンボリックリンクを逆参照しません。

-r、-再帰

コマンドラインにある場合にのみ、シンボリックリンクをたどって、各ディレクトリの下のすべてのファイルを再帰的に読み取ります。これは、-d recurseオプションと同等です。

-R、-dereference-recursive

各ディレクトリの下のすべてのファイルを再帰的に読み取ります。-rとは異なり、すべてのシンボリックリンクをたどります。


それはgrepのバージョンです。私が持っている-R, -r, --recursive Read all files under each directory, recursively; this is equivalent to the -d recurse option.2.10に
TheMeaningfulEngineer

grep(GNU grep)2.14
tijagi 14

5

zshでは、これはglob修飾子のおかげで簡単になります:

grep -- PATTERN **/*(.)

パターン**/はサブディレクトリを再帰的に横断します。glob修飾子は、.一致を通常のファイルに制限します。

zshを使用しない場合は、使用しますfindMichael Hornerの回答を参照)。そして、この特定のケースでは、GNU grepはあなたが望むことをすることができます(それはまさにgrep -rそうです)-しかし、バージョン2.12以降、以前のバージョンはシンボリックリンクをたどりました。


2

$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 (リセット)のデフォルト値は次のとおりです。

 \033 - ESCAPE
 m - END ESCAPE
 0 - reset 

...それぞれ。${type_code}は、さまざまなfi (通常のファイル-デフォルトの未設定)di (ディレクトリ)ln (リンク)、および私が知っている他のすべてのファイルタイプの代わりに使用されます。また、デフォルトで未設定であり、ここでは各行の先頭に表示される$no (通常)もあります//。私のシンプルな小さなIFS=:ブロックは、それぞれの設定可能な名前を独自の値として挿入し、スラッシュを1つまたは2つ追加する\0だけで機能しますが、NULバイトでも同様です。

デフォルトでls$rs、最初の出力の直前に1つも挿入されますが$lc、ここでは正確に表現されていません。この場合、私が指定した$ec (終了コード)のために立っている$rsすべてのケースでは-それが指定されているときに、余分な取得しない$rs$no${type_code}、あなたがそうでなければ同じように-それだけプレゼント直後にファイル名を以下出力の開始時に一度-行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:...

実際、私の小さなシェルハックはおそらく非常に複雑です。これらの値を割り当てるための広く利用可能なインターフェイスがあります。dircolors -pcliで試してみてくださいinfo dircolors。その詳細については。

任意の文字列でファイル名をラップできます。必要に応じてコメントアウトできます。ファイル拡張子のみに基づいて同様の動作を指定できます。あなたがそのように指定することができない多くは本当にありません。

今、私はこのすべてを作り上げているだけではありません- 偶然ソースコードにつまずいた後、私はそれについて学びました。

この特定の構成でlsは、以下が出力されます。

  1. $no -各レコードの開始時にレコードごとに1回

  2. ${type_code}-各ファイル名の直前に1回、ファイルの種類の略語を含め、常に同じ行にあり、シンボリックリンクのターゲットを示す後$no または直後にある7つの空白区切りフィールド->

  3. $ec -最初の行の直前に1回、その後各ファイル名の直後に1回のみ。

  4. 他のすべての値は空です。

続くものはnull区切り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^@//$

したがって、このようなongリストからすべてのシンボリックリンクを確実に削除-lするには、簡単な変更を加えることができます。

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 ...

... (ここで、fc1fc2後にリストされたファイルタイプですset --サブシェルで)確実にあなたがしたいことから、ファイルタイプのいずれかの組み合わせを削除するために役立つはずであるlsにかかわらず、ファイル名が含まれている可能性のあるすべての文字の出力を。


ねえ、素敵、独創性のために+1。ただし、ディレクトリが詰まっているようです。これらは、文字化けしたANSIカラーコードで印刷されています。とにかく、これがどのように機能するかの説明を追加できますか?おそらく、何かを説明lcncなどありますか?
テルドン

@terdon-既に環境に設定されているか、またはlsdi=値のデフォルトとしてコンパイルされているANSIエスケープでのみ出力されます。あなたはdi=:それを無効にするためにvar に追加する必要があります-そして他のすべてのために。それは私がAPIによって意味するものです-あなたは各ファイルタイプに対処しますが、すべての場合に同じようにインターフェースに対処する必要があります。そのため、ln1つの方法を設定してdiデフォルトを無視してもうまくいきません。同様に多くのデフォルトがコンパイルされています...うーん。あなたがについて尋ねるlcncとものが有効である-完全に-私はすでにかかわらず、他の日にそれをやりました。リンクします、と思います。
mikeserv 14

痛いので、可能なすべてのファイルタイプを常に指定するか、事前に何が存在するかを確認する必要がありますか?はい、ありがとう。
テルドン

@terdon-今すぐ私の編集を参照してください-シェルの数行ですべてを実行し、各タイプをタイプ名で指定し、すべてのファイル名を確実に区切ります。非印刷物も導入されていません。とにかくそのためのAPIがあります-それはですdircolors。構成ファイルを読み取り、シェルevalフレンドリーなvar値を出力します。それは非常に簡単です-しかし、そこにあるいくつかの行もそうです。とにかく、使用したい場合は、dircolors2つの異なるファイルを保存して、その方法で呼び出します。また、先日\0、各エスケープシーケンスの一部としてNUL区切り文字を使用して両方を同時に行う方法を示しました。
mikeserv 14

@terdon -私はそれがでコンパイルされるかもしれないすべての値を設定することがいかに簡単であるか、それをより明確にしようとした-私は、すべてのemを得たと思います、多分あまりにも多くを... 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
mikeserv

0

上記の答えは、次のことにつながります。

 ls -1F | grep -i "/"

奇妙なことに、lsコマンドの1を残してもリストが表示されます。


1
なんでgrep -i/大文字でも小文字でもかまいません。ls出力が端末ではない場合のデフォルトはnoe-column形式です(ここではパイプです)。
クサラナナンダ

-2

これを試してください:

ls | grep -v " -> "

2
これはさまざまな理由で失敗しますa -> b。たとえば、というファイルです。また、改行やその他の奇妙なファイル名では失敗します。lsの解析が悪い考えである理由については、これをお読みください。
テルドン

@terdonこれが失敗するより基本的な理由があります。はにlsエイリアスされls -l、ファイル名の前に列を返します。そうでない場合、シンボリックリンクに関して特別なことは行いません。
ジル 'SO-悪であるのをやめる' 14

@terdon- ls自身を解析します。ls端末に出力するたびに解析します-apiがあります。このようなことを示す回答をここに投稿しましたが、さらに多くのことができます。先日お見せしました-あなたはヌル区切りのファイル名を自分で持っていました。
mikeserv 14

@mikeserv私は知っている、知っている。ただし、これを安全に行う方法を説明するには、ご自身で実証したように数百行かかります。現状では、この回答はlsを解析するすべての危険に苦しんでおり、OPは明らかにそれらを認識していません。
テルドン

@terdon- lsあなたの子供や何かを食べるつもりはありません-それはただのプログラムです。あなたはそれを説明していない場合、それはなります、それを説明するために数百を取ると、あなただけの間違っているにリンクされている理由を数百行を説明するために、より多くの数百を。それに-これは2つだけの行である:LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \ ls -1 --color=always | cat
mikeserv

-3

このコマンドを試してください: ls -p | grep -v @


いいえ、リンクをリストします。
TheMeaningfulEngineer 14

@Alan:kはこれを試すfind -type f
Thushi

1
-1理由:i)-pディレクトリーにスラッシュを追加するだけで、探しているのは-Fii)findディレクトリーをリストしない代替手段である、iii)投稿する前に答えをテストしてください。
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.