lsは、rmが削除するファイルを常にリストしますか?


33

私が確かに知っておくべきだと思うこと:私が表示した場合ls <something>rm <something>まったく同じファイルを削除しlsますか?表示さrmlsなかったファイルを削除できる状況はありますか?(これは18.04 bashにあります)

編集:答えたすべての人に感謝します。完全な答えはすべての答えの組み合わせであると思うので、私は最も回答の多い答えを「答え」として受け入れました。

途中で学んだ予期しないこと:

  • ls 引数の処理で考えるほど簡単ではない
  • Ubuntuの単純な未調整インストールでは、.bashrcエイリアス ls
  • コマンドの引数のように見える可能性があるため、ダッシュで始まるファイルに名前を付けないでください。-rという名前を付けると、それが要求されます。

8
フラグrmがないことに少し驚いてい--dry-runます
...-fkraiem

20
@Rinzwindなぜfind -deleteより良いでしょうrmか?あなたは「それが理由」と言いますが、それが何を指しているのか私には完全に不明です。また、find呼び出しにより、現在のディレクトリ内のすべてのファイルが再帰的rm削除され、直接のディレクトリ内のファイルが削除されることに注意してください。また-name *、ノーオペレーションです。全体として、私はあなたのアドバイスにかなり困惑しています
...-marcelm

3
@marcelm使用するfindためのアドバイスは、それを実行し、すべてのファイルを表示し、で同じコマンドを実行できるからだと思います-delete。からの結果を既に見たのでfind、削除されるものにあいまいさはないはずです(これについての詳細は回答の形で聞きたいです)
Scribblemacher

5
@Scribblemacher "...あなたはそれを実行し、すべてのファイルを表示し、同じコマンドを-delete"で実行できます -しかし、実行するよりも優れているのはls <filespec>、その後に続くrm <filespec>(OPはすでにその方法を知っています)?
marcelm

12
@Rinzwind 「これは、lsの後、rmの前にファイルが作成されるというインスタントに対するchorobaの答えを解決します。」-いいえ、そうではありません。find ... -print最初に実行して削除するファイルを確認し、その後find ... -delete、2つのコマンドの間に作成されたファイルを削除します。-printとの両方を使用すると-delete、確認は行われず、削除された内容の事後レポートだけが表示されます(使用することもできますrm -v)。
マーセル

回答:


40

さて、両方lsrmそれらに渡される引数を操作します。

これらの引数はそう単純なファイル可能ls file.extrm file.ext同一ファイル上で動作し、結果は明らかです(リストファイル/ファイルを削除します)。

代わりに、引数がディレクトリの場合、ls directoryリストの内容ながら、ディレクトリのrm directoryように動作しませんが(つまりrm、あなたがしなければしながら、フラグなしでは、ディレクトリを削除することはできませんrm -r directory、それは再帰的に削除し、すべてのファイルの下directory やディレクトリ自体を)。

ただし、コマンドライン引数はシェル展開の対象になる可能性があるため、ワイルドカード、変数、他のコマンドからの出力などが含まれている場合、同じ引数が両方のコマンドに渡されることが常に保証されるわけではありません。

極端な例としてとを考えるls $(rand).txtrm $(rand).txt、引数は「同じ」ですが、結果はまったく異なります!


3
また、考慮lsrm *私は書いていないとしてそこに「隠される」(ドット)ファイル、しかしでも、すべての公正な比較でのないことls *。しかしrm、それ自体は無意味なので、全体は本当にリンゴとオレンジです。私が正しく理解していれば、それはあなたの答えの核心であり、とても良い仕事です:)
モニカとの軽度のレース

5
上のもう一つのコメントlsrm -rコマンドは:ls <directory>ディレクトリ内の隠しファイルを表示しませんが、rm -r <directory> としても隠しファイルを削除します。
ダニエルワグナー

1
@LightnessRacesinOrbit lsは(それらにエイリアスされていない限り)それらをリストせずls -arm *それらを削除しません(dotglob設定していない限り)。
停止ハーミングモニカ

20

ls foo*.txtvs.のようなものを考えている場合rm foo*.txtは、はい、同じファイルを表示して削除します。シェルはグロブを展開し、問題のコマンドに渡します。コマンドはリストされたファイルで機能します。それらをリストするもの、削除するもの。

明らかな違いは、これらのファイルのいずれかがディレクトリになった場合、lsその内容をリストしますが、rm削除に失敗することです。これは通常、問題ではありません。なぜなら、で示されたものよりも少ないものrmを削除するからです。ls

ここでの大きな問題は、ダッシュls *またはダッシュで始まるファイル名rm *を含むディレクトリで実行することから生じます。彼らは、あなたが自分でそれらを書いたかのように2つのプログラムのコマンドラインに拡大する、とls取る-r一方で、「逆のソート順」を意味するrmかかるだろう-r再帰的に除去することを意味します。少なくとも2レベルの深さのサブディレクトリがある場合、違いは重要です。(ls *最初のレベルのディレクトリの内容を表示しますがrm -r *、最初のサブレベル以降もすべて表示されます。)

それを避ける./には、現在のディレクトリを示すために先頭に許可グロブを記述し、および/または--グロブの前にオプション処理の終了を通知するためにa を置きます(つまりrm ./*またはrm -- *)。

のようなグロブで*.txtは、ドットは無効なオプション文字であるため実際には問題ではなく、エラーが発生します(誰かがユーティリティを展開してその意味を発明するまで)が、./とにかくそこに置く方が安全です。


もちろん、シェルのグロビングオプションを変更した場合、またはコマンド間でファイルを作成/移動/削除した場合、2つのコマンドで異なる結果が得られる可能性がありますが、これらのケースのいずれかを意味するものではありません。(新規/移動されたファイルを扱うことは、安全に行うには非常に面倒です。)


1
ありがとうございました。これは、コマンドライン構文全体の問題を浮き彫りにしているようです。ダッシュで始まるファイルに名前を付けると、危険な海域を航行していることになります。-ファイルを忘れてからずっと経って、将来どのコマンドを使用する可能性があるかを誰が知っていますか。
B.Tanner

1
@ B.Tanner、はい。ある意味では、問題はコマンドライン引数が単なる文字列であることです。システムが今日設計されている場合、実行されるプログラムが引数がオプションフラグであるかどうかを認識できるように、より多くの構造が存在する可能性があります。ファイル名の非常に緩い構造に起因する他の問題もあります。dwheelerによるそれについての非常に徹底的なエッセイがありますが、私はそれを読むことは傷つくだろうと警告しなければなりません。(詳細から、または何が間違っている可能性があるかというひどさから)
。– ilkkachu

3
私は抵抗することはできません、あなたは私にそれを売りました、私は今それを読みに行きます、多くのファイル名の終わりにキャリッジリターン文字を得ることができたときの思い出とともにbashスクリプトとしても実行できるWindowsバッチファイルを作成します...それが来るのを見ていませんでした!)
B.Tanner

17

ものだけではさておきシェル行動、レッツ・フォーカスを離れるrmと、ls自分自身を扱うことができます。削除できないlsものを表示する少なくとも1つのケースにはrm、ディレクトリのアクセス許可と、その他の特別なディレクトリ.とが含まれ..ます。

フォルダーのアクセス許可

rmファイルを削除すると、ディレクトリの内容が変更されるため(つまり、ディレクトリはファイル名とiノードのリストにすぎないため、ディレクトリエントリのリストになっているため)、ディレクトリに対する操作です。つまり、ディレクトリに対する書き込み権限が必要です。ファイルの所有者である場合でも、ディレクトリのアクセス許可がないと、ファイルを削除できません。逆もまた真であるrmあなたは、ディレクトリの所有者であれば、他の人が所有することができるファイルを削除することができます。

非常によく読んで、たとえば、あなただけの罰金内のディレクトリ、コンテンツを見るを通過できるようになりますディレクトリ、上の権限を実行している可能性がありますので ls /bin/echo、しかし、あなたがすることはできませんrm /bin/echoあなたが所有者でない限り、/bin またはを使用して権限を昇格sudo

そして、あなたはこのようなケースをどこでも見るでしょう。そのようなケースの1つを次に示します。https//superuser.com/a/331124/418028


特別なディレクトリ '。' および「..」

もう1つの特別なケースは...ディレクトリです。ls .またはを実行ls ..すると、コンテンツは喜んで表示されますが、rm「許可」は許可されません。

$ rm -rf .
rm: refusing to remove '.' or '..' directory: skipping '.'

15

あなたが入力した場合ls *、その後rm *、それが可能だ、あなたはより多くのファイル削除しますls彼らはの端部との間の小さな時間間隔で作成されている可能性があります-示したのlsとの開始しますrm


1
これ/tmpは、多くのアプリケーションが一時ファイルを作成できる可能性のあるケースです。そのため、両方のコマンドでを使用することは常に可能*です。ただし、アプリケーションによってはunlink()、ファイルハンドルを開いたままファイルを匿名化することでファイルを匿名化するため、表示されls *rm *もキャッチされない場合があります。
セルギーKolodyazhnyy

1
@OrangeDogポイントがありません。私たちは、競合状態の話をしている
Sergiy Kolodyazhnyy

1
@OrangeDog私は今電話をしているのでこれを確認する必要がありますが、ディレクトリの内容のリストが変更されているため、表示される内容と動作する内容に*違いがある場合でもポイントは変わりlsませんrm
セルギーKolodyazhnyy

1
コマンドを1つしか実行しない場合でも、引数を展開してから削除するまでに競合状態があります。
停止ハーミングモニカ

1
@OrangeDog同意できます。ワイルドカードの展開は既存のファイル名で機能するため、はい、ワイルドカードを展開するシェルとそれを処理するコマンドとの間に競合状態があるためls *、実際には既に存在しないファイル名を表示する可能性があります。
セルギーKolodyazhnyy

9

ls *そしてrm *、グロブを展開する責任はありません-それはコマンドに渡す前にシェルによって行われます。

これは、拡張されたファイルリストで任意のコマンドを使用できることを意味します。したがって、できる限り使用しないものを使用します。

したがって、これを行うためのより良い方法(または少なくとも、別の方法)は、仲介者をスキップすることです。

echo *rmコマンドに渡されるものを正確に表示します。


2
ありがとう、私はこのシナリオでlsの代わりにエコーを使用するというアイデアが好きです。
B.Tanner

3
またはprintf "%s\n" *、スペースを含むファイル名の明確なビューを取得します。(または、%q代わりに改行と制御文字も処理しますが、い出力を犠牲にします。)
ilkkachu

4

どうですか:

$ mkdir what
$ cd what
$ mkdir -p huh/uhm ./-r
$ ls *
uhm
$ rm *
$ ls
-r
$ ls -R
.:
-r

./-r:

基本的にワイルドカード--、で始まるもの(または手動で入力されたものから始まりますが、それは少し不正行為のように見えます)は、とで解釈が異なる場合がlsありrmます。


4

表示されるものが削除されるものではないエッジケースがあります。かなり極端ですが、幸いなことに、渡す引数がディレクトリへのシンボリックリンクである場合、シンボリックリンクされたディレクトリ内のすべてのファイルが表示され、シンボリックリンクが削除され、元のディレクトリとその内容は変更されません。lsrmlsrm

% ln -s $HOME some_link
% ls some_link    # Will display directory contents  
bin    lib    Desktop ...
% rm some_link
% ls $HOME
bin    lib    Desktop ...

1
ほら 私のためにln -s $HOME some_link; ls some_link出力some_link@しますが、私はにlsエイリアスしていls -Fます。どうやら、-F動作を変更して、リンクを間接参照するのではなく、リンクを表示するようにします。それを期待していませんでした。
マーセル

確かに!またls -l、たとえば、リンク先ではなくリンクを対象としています...リンク自体を検査する方法が必要です。
アレクシス

1
質問にオプションを追加すると、あまりにも多く開かpossibilities--私の答えは、無修正の行動についてであるlsrm
アレクシス

あなたが言う場合ls some_link/、  ls -H some_linkまたはls -L some_link、それはあなたが追加した場合でも、リンク先のディレクトリの一覧が表示されます-F-l。逆に(並べ替え)、-dコンテンツではなくディレクトリを見るように指示します。と比較ls -l /tmpls -ld /tmpます。
G-Manが「Reinstate Monica」と言う

もちろん、の動作を変更するフラグを追加できますls。基本的に、異なるフラグを使用した動作の列挙がこの質問の
わずらわしさに

4

あなただけ行う場合lsの代わりにls -a、はいrmあなたが見ていない隠されたファイルは削除することができlsなくては-a

例:

による :

dir_test
├── .test
└── test2

ls dir_test :test2のみを表示します

ls -A dir_test :test2 + .testを表示します

rm -r dir_test :すべてを削除します(.test + test2)

それがお役に立てば幸いです。


例を挙げていただけますか?通常、rm *ドットファイルは削除しないためです。存在する場合は、ls *それらも表示されます。
マーセル

いいえ、ls *隠しファイルを表示しません。
DevHugo

しかし、はい、それは少し混乱しています、私はいくつかの例を追加しました。
DevHugo

1
ls -a一覧表示されます....testtest2。を使用するように例を変更したい場合がありますls -A。これはand を除く すべてリストします(つまり、and のみ)。....testtest2
G-Manが「Reinstate Monica」と言う

3

すでに多くの良い答えがありますが、もう少し深い洞察を加えたいと思います。

自分自身に質問をする:に渡されるどのように多くのパラメータls、あなたが書く場合

ls *

...?展開可能なファイルがある場合、lsコマンドは*asパラメーターを取得しないことに注意してください*。代わりに、シェルはコマンドを呼び出す前に最初にグロビングを実行するため、lsコマンドは実際にグロビングに一致するファイルと同じ数のパラメーターを取得します。グロビングを抑制するには、パラメーターを引用します。

これはすべてのコマンドに当てはまります:echo *vs echo '*'

スクリプトがあり、それcountparams.shを呼び出して効果をテストします。渡されたパラメーターの数を示し、それらをリストします。

#!/bin/bash
echo "This script was given $# parameters."
arr=( "$@" )
for ((i=0;i<$#;i++)); do
        echo "Parameter $((i+1)): ${arr[$i]}"
done

実行可能にして実行します./countparams.sh *。その出力から学ぶ!


1

ディレクトリの内容がそれらの2つの異なる時間で同じである場合、グロブは両方の時間で同じように拡張します。


削除するものを本当に確認したい場合は、を使用しますrm -i *.txt。ファイルを削除する前に、ファイルごとに個別にプロンプ​​トが表示されます。

これにより、競合状態に対して安全であることが保証されます。/
        ls *.txt新しいファイルが作成されrm *.txt
ます。


これは、通常の使用のためにあまりにも面倒であり、エイリアス場合rmrm -i、あなたは使用して自分自身を見つけるでしょう\rmrm -f、多くの場合、かなり。しかし、少なくとも競合状態の解決策があることに言及する価値があります。(それは非GNUシステムにも移植可能です:POSIX rm(1)-iオプションを指定します。)

もう1つのオプションはbash配列ですto_remove=(*.txt)。次に、(おそらくを実行した後にls -ld -- "${to_remove[@]}") ユーザーに確認を求め、次にを要求しますrm -- "${to_remove[@]}"。そのため、glob展開は一度だけ行われ、リストはにそのまま渡されrmます。

もう1つの実用的なオプションはGNU rm -Imanページ)です。これは、4つ以上のアイテムを削除する場合にプロンプ​​トを出します。(ただし、リストは表示されず、合計のみが表示されます。)私alias rm='rm -I'はデスクトップで使用しています。

あまりにも一致するハーフタイプのパターンを使用すると、脂肪の多い戻りに対する優れた保護手段になります。ただし、ls最初に使用することは、一般に、所有するディレクトリまたはシングルユーザーシステムで、非同期的に新しいファイルを作成できるバックグラウンドプロセスがない場合に適しています。太りすぎを防ぐためにrm -rf /foo/bar/baz、左から右に入力しないでください。 rm -rf /特別なrm -rf /usr場合ですが、そうではありません!-rfパーツを除外するか、から始めてlsrm -rfパスを入力した後にのみパーツを追加します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.