ファイル名に非印刷文字が含まれているファイルを削除するにはどうすればよいですか


46

どういうわけか、ファイル名がないように見えるファイルを作成することができました。次のスレッドでファイルの詳細を取得する方法に関する情報を見つけました

しかし、リストされている提案のいくつかを試してみたところ、ファイルを削除できないようです。私はそれを作成するために何をしたのか分かりませんが、xmlファイルをコピーしようとしたときに起こりました。

ファイルに関するいくつかの情報は次のとおりです。

> ls -lb
total 296
-rw-r--r--   1 voyager  endeavor  137627 Jan 12 12:49 \177

> file *
:               XML document

> ls -i
 417777   

私はinumスイッチを使って見つけてそれをrmにパイプしようとしましたが、それはそれを取り除く最も確実な方法のように見えました。ただし、下にリンクされているスレッドの下部にある例は失敗しました。例は:

> find -inum 41777 -exec ls -al {} \;
find: illegal option -- i
find: [-H | -L] path-list predicate-list

だから私は次のように最初にパスリストを使用しようとしましたが、それも機能しませんでした:

> find . -inum 41777 -exec ls -al {} \;

非印刷文字\ 177が何であるか、またはrmコマンドにそれをどのように渡すことができるかはわかりませんが、このファイルを削除しようとして、他のファイル/ディレクトリを台無しにしないようにしたいです。


1
\177はASCII DEL文字です。
キーストンプソン

9
417777!= 41777
CVn

素晴らしい点マイケル。それがおそらく私のコマンドが機能しなかった理由です。
ムース氏

@KeithThompson先行なしの8進数0ですか?

1
@cat:このコンテキストでは、はい。文字列および文字リテラルのC構文に従います。
キーストンプソン

回答:


46

ファイルには名前がありますが、印刷できない文字で構成されています。ksh93、bash、zsh、mksh、またはFreeBSD shを使用している場合は、印刷できない名前を指定して削除しようとすることができます。まず、名前が正しいことを確認しls -ld $'\177' ます。正​​しいファイルが表示されている場合は、rmを使用します。rm $'\177'

別の(もう少し危険な)アプローチはを使用することrm -i -- *です。-iオプションを使用すると、rmはファイルを削除する前に確認を要求するため、1つ以外の保持するすべてのファイルをスキップできます。

幸運を!


1
rm -i *この場合はうまくいかなかったと思う。改行のため、シェルはファイル名として認識されない*ものに展開rmされます。
キーストンプソン

6
@KeithThompson:シェルのグローブ拡張は、それ以上の解釈の対象ではありません。展開された名前に改行が含まれていない限り、改行はありません。
クリストファーハンマルストローム

@ChristofferHammarström:うーん。いくつかの実験を行い、さらにコメントします。
キーストンプソン

@ChristofferHammarström:ファイル名に改行文字が含まれているため、展開された名前に改行があります。しかし、私はbashGNU を過小評価しているようrmです。私のシステムでrm *rm -i *rm Ctrl-V DEL TAB ENTERファイル名に改行文字が含まれていても、、、すべてが正しく機能します(私はを使用しました"\177foo\nbar\n")。一部のコマンドはそのようなファイル名をうまく処理しませんが、GNUツールは堅牢に見えます。同じツールの非GNUバージョンも同様に動作しない可能性があります。いずれにせよ、これらの答えのさまざまなトリックは知っておくと便利です。
キーストンプソン

1
@KeithThompsonは、任意のシェルは、bashのではないだけを正しくグロブファイルを処理していない、となりますrm決してそれはGNUのかどうかの単語分割のいずれかの形式んrmかないの。シェルはグロブを展開し、呼び出されたコマンドを実行すると、結果のファイル名をヌルで区切られた引数として(Cコードで)渡します。危険なのは、ファイルのリストを区切り文字として改行を使用するものにパイプすることです。見るのはなぜ見つけるの出力悪い習慣をループされますか?
ワイルドカード

23

vim現在の作業ディレクトリで実行するユーザーの場合:

$ vim ./ 

矢印キーまたはでファイルに移動しますj/k。次にShift+D、を押して削除を確認しますy


私は一般的にvimが怖いですが、それは本当にうまく
いきました-tofutim

9

おそらくファイル名をに渡す方法はありますがrm、何かを台無しにすることが心配な場合は、GUIファイルマネージャを使用できます。Emacsには、インストールされている場合に使用できるディレクトリ編集モードが付属しています。

  1. でフォルダを開きますemacs。を実行するemacs /path/to/folderか、emacsを開いてEsc+を押しx、runを実行diredすると、パスの入力を求められます

    http://so.mrozekma.com/unix-dired-delete1.png

  2. 削除するファイルがある行に移動して、を押しdます。Dファイルの横の左マージンにが表示されるはずです。

    http://so.mrozekma.com/unix-dired-delete2.png

  3. を押しxて変更を保存します。ファイルの削除を確認するプロンプトが表示されます。プレスy

    http://so.mrozekma.com/unix-dired-delete3.png


1
素晴らしいアイデアのように見えますが、このマシンでemacsを見つけることができないようです。聖戦を開始するリスクがある...これをvimで行うことはできますか?
ムース氏

2
使う人のためにvim:現在の作業ディレクトリでそれを実行しvim ./、矢印キーを使用してファイルへとナビゲート。次にShift+D、を押して削除を確認しますy

@hesseすごい。私がvimサポートすることを期待したものではありません
マイケルMrozek

1
@MichaelMrozekは同意しました。これには、私がときどき発見する傾向のあるこれらすべての機能があります。

1
@ケビンnyanモード:nyan-mode.buildsomethingamazing.com
ティム

8

file *シェルグロブ(*)がこのファイルを取得できることは既に実証済みであるため、ここrmでそのグロブを実行します。

  • ファイルがあるディレクトリに移動します。
  • 走る rm -i *
  • n一見見えないファイル名のファイルを除くすべてのファイルを入力します

7

ファイルには実際には名前がありますが、印刷できない文字で構成されています。

簡単な方法は、シェルの補完に依存することTabです。「奇妙な」ファイル名が挿入されるまで繰り返し押します。可能な完了間を循環するようにシェルを構成する必要があります。

  • bashで、あなたが呼び出すために必要なmenu-completeのではなく、デフォルトではバインドされていない、completeにバインドされ、Tabデフォルトで。または、Esc *すべてのファイルの補完を挿入するために使用し、コマンドラインから削除したくないものを削除します。
  • zshでは、デフォルト設定で問題ありません。あなたが持っているsetopt auto_menuか、setopt menu_complete設定する必要があります。

シェルで補完が役に立たない場合はrm -i -- *、この特定のファイルを除いて「no」を呼び出して答えることができます。ファイル名が印刷可能な文字で始まらない場合、最初の文字が印刷可能な文字のセットにないファイルに一致を制限できます。

rm -i [!!-~]*
rm -i [![:print:]]*
rm -i -- [!a-z]

(パターンがと呼ばれるファイルに一致する可能性があることに注意してください。-fこれrmはオプションとして扱われます。)

別の方法はls -i、ファイルのiノード(iノードが特定のファイルシステム上のファイルを一意に識別する)を見つけて呼び出しfind -inum、その特定のファイルを操作することです。この方法は、ディレクトリに多くのファイルが含まれる場合に最も役立ちます。

ls -i
# note the inode number 12345
find . -xdev -inum 12345 -delete

オプションfindがない場合は-delete、電話してrmください:

find . -xdev -inum 12345 -exec rm -- {} \;

(はい、私はこれの大部分がすでに投稿されていることを知っています。しかし、関連する情報の答えは、これを本来よりも複雑にしています。)


4

を使用echo -eして文字を取得し\177、それxargsをに渡しrmます。echo進エスケープを取るので、進に変換しません:判明177進です。前に(nullバイトではなくリテラル)echoが必要\0です:

echo -ne '\0177\0' | xargs -0 rm

\ xb1 \ 0は\ 177の16進表現であると言っていますか?
ムース氏

@MrMoose \xb1はdecimalで177\0NULLで終了し、改行で終了する名前の代わりにNULLで終了する名前を取るように-0指示xargsします。
ケビン

SunOSでbashを使用していますが、コマンドを試したときにxargs:illegal option-0が返されました。manページを見て、null終了のオプションが見つかりませんでした。私は今でも問題の修正を取得することができました。回答としてマークされた応答を参照してください。
ムース氏

your echoは、2つのファイル名をそのままxargsに送信しrm、2番目のファイル名は\n..になります。これにより、エラーが発生するか、その名前のファイル( '\ n')を削除します
Peter。 O

@pererはい、私はそのことに気づきました。-n改行を削除するために追加しました。
ケビン

3

私はちょうど約ファイルがことを保証することができません名前を持っています。それはたまたま印刷不可能な文字を含む名前です。

rm動作しなかった場合はfind-inumオプションでの出力を引数として使用しrmても役に立たない可能性があります。rm同じ問題で、同じ引数をに渡すだけです。

ファイルはそのディレクトリ内の唯一のファイルですよね?

最初に試すのはcd、ディレクトリに移動してからを入力しrm ./、Tabキーを押すことです。これにより、引数がファイルの実際の名前に展開され、前述の例で./rm引数がファイル名以外のものとして解釈されないようにする必要があります。

別の解決策はcd、親ディレクトリに移動し、そのディレクトリでrm -r(または必要に応じてrm -rf)使用することです。名前に関係なく、ディレクトリとそのすべてのコンテンツが削除されます。その後、を使用mkdirしてディレクトリを再作成できます(そして、おそらくchmodそのアクセス許可を復元します)。

編集:

ls -lb出力をもう一度見ると、ファイル名はASCII DEL文字で始まり(致命的ではなく悪くない) 1つ以上の改行文字(実際には悪い)が含まれていると思います。私が知る限り、rmコマンドはファイル名の一部として改行を解釈できません。

しかし、unlink()システムコールはできます。以下に、私が一緒に投げたPerlスクリプトを示します。このスクリプトは、現在のディレクトリ内のファイルを反復処理し、削除するかどうかを各自に尋ねます。rmファイルを削除するような外部コマンドを使用しないので、ファイルシステムがサポートしている変な文字(ASCII NULおよび以外のもの/)を処理できるはずです。

こうrm -rrm -rf含むディレクトリにはまだ動作するはずですが、あなただけの1つのファイルを削除したい場合は、これを試すことができます。

#!/usr/bin/perl

use strict;
use warnings;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    my $pfile = printable($file);
    print "Remove $pfile? ";
    my $answer = scalar <STDIN>;
    if ($answer =~ /^[Yy]/) {
        print "Removing $pfile\n";
        unlink $file or warn "Unable to remove $pfile: $!\n";
    }
}

sub printable {
    my($s) = @_;
    $s =~ s/[^ -~]/?/g;
    return $s;
}

(別の解決策は、保持したいディレクトリに他のファイルがある場合、他のすべてのファイルを一時ディレクトリに移動し、ディレクトリを破棄して再作成し、他のファイルを戻すことです。)

(ああ、そしてあなたがそのファイルを作成するためにしたことは何でも、それを二度としないようにしてください!)


1

コマンドを使用してそのファイルを正確に検索findできる場合は、-delete述語を使用できます。ただ注意して、-deletefindコマンドの最後のパラメーターを作成します。


1

あなたは近いです。ステップバイステップで、iノード番号でファイルを削除する方法を示します。

まず、を使用して、目的のファイルのiノード番号を見つけますls -li。iノード番号は、出力の最初の列にあります。

例えば:

$ls -li
311010 -rw-rw-r-- 1 me me 3995 Apr  6 16:27 -???\# ;-)

この場合、iノード番号は311010です。

findiノード番号でファイルを探すために使用します。

find . -inum 311010 

ていることを確認してくださいfindだけで、削除したいファイルの名前を返します。例えば:

$find . -inum 311010
./-???\# ;-)

find正しいファイルが見つかったことを確認したら、-deleteパラメータをに渡しますfind。ファイルが削除されます。

find . -inum 311010 -delete

0

他の答えは素晴らしく、ほとんどすべての環境で機能します。

ただし、GUIを実行している場合は、nautilus、dolphin、konqueror、またはお気に入りのファイルマネージャーでディレクトリを開くだけで、マウスを数回クリックするだけで、非協力的な名前のファイルを簡単に表示および削除できるはずです。 。

あなたが通常のemacsやvimユーザーでない場合(他のいくつかの回答で紹介されています)、これが最も簡単な方法かもしれません。


0

「\ 033」(実際の「エスケープ」文字)という名前のファイルでも同様の問題がありました。

for x in $( ls | awk '!/^[A-Z]/ && !/^[a-z]/ && !/^[0-9]/');do rm -i -- $x ; done

上記の例では、文字または数字で始まっていない現在のディレクトリ内のファイルを削除するよう求められます。


0

代わりに、現在のディレクトリの名前をに変更DirX_OLDして、その名前で新しいディレクトリを作成DirXし、必要なすべてのファイルをからDirX_OLDに移動できますDirX。ファイルをコピーした後、削除できますDirX_OLD


0

念のため、2セントの価値を追加する人を助けます。次のようにstatワイルドカードを使用してファイル名を取得できました:

stat -c %N *

出力:

`\220g\201\acontexts'
`\220g\201\alogins'
`\220g\201\amodules'
`\220g\201\apolicy'
`\220g\201\asetrans.conf'

次に、ANSI C引用符で囲まれた文字列(受け入れられた回答で使用)を使用してファイルにアクセスできます。

rm $'\220g\201\asetrans.conf'

0

すべてのファイルには名前があり、正確にどれを見つける必要があります。

このファイルを例として使用します。

$ touch $'\177' $'\001\002' $'\033\027' a b abc $'a\177b'

これらのファイルは?通常どおり表示されますls

$ ls
??  ?  ?002  a  abc  b

ただしls-Qオプションを許可する場合は、実際のファイル名を明確にする必要があります。

$ ls -1iQ *
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"
26739118 "a"
26739121 "a\177b"
26739120 "abc"
26739119 "b"

これらは、1pwd内のファイルの列にあるiノード番号と「引用」名です。

それは、拡張(グロビング)を使用するために(POSIX)シェルの能力を使用しています。

名前に非印字文字を含めるには:

$ ls -1iQ *[![:print:]]*
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"
26739121 "a\177b"

そして、非印刷文字のみを含む可能性のあるファイルをリストするには:

$ ls -1iQ [![:print:]]*
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"

次に、選択的に(-i(インタラクティブ)オプション)それらを削除するには、以下を使用します。

$ rm -i [![:print:]]*
rm: remove regular file ''$'\001\002'? n
rm: remove regular file ''$'\033\027'? n
rm: remove regular file ''$'\177'? n

y上記の質問に答えて、消去するものを選択するだけです。


0

オートコンプリート機能を備えたbashを使用している場合は、これが有効な場合があります。ディレクトリリストに表示されている文字を入力しました。その後、オートコンプリートをトリガーし、その名前を印刷可能なものに変更しました。

ここに私のために働いたものがあります:

$ ll
-rw-r--r--.  1 xxxxxxxx  xxxxx 25608 Oct 11 11:11 ?
$ mv ?  
(hit the [tab] and it gets extended to ...)
$ mv ^[
(now complete the command and rename to something printable)
$ mv ^[ weirdchar
$ ll
-rw-r--r--.  1 xxxxxxxx  xxxxx 25608 Oct 11 11:11 weirdchar
(now delete)
$ rm weirdchar

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