Dosya adının yazdırılmayan karakterleri olan bir dosyayı nasıl silebilirim


46

Her nasılsa dosya adı görünmeyen bir dosya oluşturmayı başardım. Aşağıdaki iş parçacığında dosyanın daha fazla ayrıntı elde etmek için bazı bilgiler buldum .

Ancak, listelenen önerilerden bazılarını denedim ve dosyayı silemiyorum. Bunu oluşturmak için ne yaptığımdan emin değilim, ancak bir xml dosyasını kopyalamaya çalışırken oldu.

Dosyadaki bazı bilgiler aşağıdaki gibidir;

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

> file *
:               XML document

> ls -i
 417777   

Ben inum anahtarını kullanarak bulmaya çalıştım ve daha sonra onu almanın en kusursuz yolu gibi görünüyordu. Ancak, aşağıda bağlantılı ipliğin altında verilen örnek benim için başarısız oldu. Örnek:

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

bu yüzden önce aşağıdaki gibi yol listesini kullanmayı denedim, ancak bu da işe yaramadı:

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

Yazdırılamayan karakterin \ 177 ne olduğundan emin değilim veya bunu bir rmkomuta nasıl geçirebilirim , ancak bu dosyayı silme denememde başka herhangi bir dosyayı / dizini mahvetmediğimden emin olmak istiyorum.


1
\177ASCII DELkarakteridir.
Keith Thompson

9
417777! = 41777
CVn

Mükemmel nokta Michael. Muhtemelen emrim hiç bu yüzden işe yaramadı.
Bay Moose

@KeithThompson Lider olmadan octal mı 0?
kedi

1
@ cat: Bu bağlamda, evet. Dize ve karakter değişmezleri için C sözdizimini izler.
Keith Thompson,

Yanıtlar:


46

Dosyanın bir adı var, ancak yazdırılamayan karakterlerden oluşuyor. Ksh93, bash, zsh, mksh veya FreeBSD sh kullanıyorsanız, yazdırılamayan adını belirterek kaldırmayı deneyebilirsiniz. Öncelikle adın doğru olduğundan emin olun: ls -ld $'\177' Doğru dosyayı gösteriyorsa, rm kullanın:rm $'\177'

Başka (biraz daha riskli) bir yaklaşım kullanmaktır rm -i -- *. -İ seçeneği ile rm, bir dosyayı kaldırmadan önce onay gerektirir, böylece saklamak istediğiniz tüm dosyaları atlayabilirsiniz.

İyi şanslar!


1
rm -i *Bu durumda işe yaramayacağından şüpheleniyorum ; yeni satırlar nedeniyle kabuk , dosya adı olarak tanımayacak bir *şeye genişleyecekti rm.
Keith Thompson

6
@KeithThompson: Kabuktaki küre genişlemesi daha fazla yorumlamaya tabi değildir. Genişletilmiş adda, içermediği sürece yeni bir satır olmaz.
Christoffer Hammarström,

@ ChristofferHammarström: Hmm. Bazı deneyler yapacağım ve daha fazla yorum yapacağım.
Keith Thompson

@ ChristofferHammarström: Dosya adında yeni satır karakterleri bulunduğundan genişletilmiş adında yeni bir satır var. Ama görünüşte hafife aldım bashve GNU rm. Benim sistemde, rm *, rm -i *ve rm Ctrl-V DEL TAB ENTERtüm çalışma doğru, dosya adı satır karakteriyle (kullandığım içerse bile "\177foo\nbar\n"). Bazı komutlar bu tür dosya adlarını iyi işlemez, ancak GNU araçları sağlam görünüyor; aynı araçların GNU dışı versiyonları da aynı şekilde davranmayabilir. Her durumda, bu cevaplardaki çeşitli hileleri bilmek faydalıdır.
Keith Thompson

1
@KeithThompson, herhangi bir kabuk, yalnızca Bash'i değil aynı zamanda dosya dolaştırıcılığını da doğru şekilde ele alır ve rmGNU olsun rmya da olmasın , hiçbir şekilde hiçbir kelime bölme yapmaz. Kabuk, küreleri genişletir ve çağrılan komutu yürüttüğünde, ortaya çıkan dosya adlarında boş ayrılmış argümanlar (C kodunda) olarak geçer. Ne tehlikeli olan boru kullanan bir şeye dosyaların bir listesini yeni satır sınırlayıcı olarak; bkz. Neden döngü üzerinde bulgunun çıktısı kötü oluyor?
Joker

23

Kullananlar vimiçin geçerli çalışma dizininde çalıştırın:

$ vim ./ 

ve ok tuşlarını kullanarak dosyaya gidin j/k. Ardından tuşuna basın Shift+Dve ile silme işlemini onaylayın y.


i genellikle vim korkuyor olsun, ama bu gerçekten iyi çalıştı
tofutim

9

Dosya rmadını iletmenin muhtemelen bir yolu vardır , ancak bir şeyi karıştırmaktan endişe ediyorsanız, bir GUI dosya yöneticisi kullanabilirsiniz. Emacs, yüklediyseniz kullanabileceğiniz bir dizin düzenleme modu ile birlikte gelir:

  1. Klasörü içinde açın emacs. emacs /path/to/folderYolları isteyecek emacs çalıştırabilir veya açabilirsiniz, Esc+ tuşlarına basıp xkoşabilirsiniz.dired

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

  2. Silmek istediğiniz dosya ile satırın üzerine gelin ve tuşuna basın d. DDosyanın yanında sol kenarda bir tane görmelisiniz :

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

  3. xDeğişikliklerinizi kaydetmek için düğmesine basın . Dosyayı silmek istediğinizden emin olmak ister; basın y:

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


1
Harika bir fikir gibi görünüyor, ancak bu makinede emacs bulamıyorum. Kutsal bir savaş başlatmanın riski altında ... bu vim içinde yapılabilir mi?
Bay Moose

2
Kullananlar vimiçin geçerli çalışma dizininde çalıştırın: vim ./ve ok tuşlarını kullanarak dosyaya gidin. Ardından tuşuna basın Shift+Dve ile silme işlemini onaylayın y.

@hesse Wow. vimDesteklememi beklediğim bir şey değil
Michael Mrozek

1
@MichaelMrozek, zaman zaman keşfetmeye meyilli olduğum tüm özelliklere sahip olduğunu kabul etti.


8

Daha önce file *kabuk globunun ( *) bu dosyayı alabildiğini gösterdin, o yüzden şimdi sadece rmbu küre üzerinde bir şey yap.

  • Dosyanın bulunduğu dizine geçin.
  • Çalıştırmak rm -i *
  • nGörünmez şekilde görünen dosya adına sahip olanlar dışındaki tüm dosyalar için girin .

7

Dosyanın aslında bir adı var, ancak yazdırılamayan karakterlerden oluşuyor.

Kolay bir yöntem kabuk tamamlamaya güvenmektir: Tab“garip” dosya adı girilene kadar arka arkaya basın . Mümkün kabiliyetler arasında geçiş yapmak için kabuğunuzun yapılandırılmış olması gerekir:

  • Bash, sen çağırmaya gerek menu-completeziyade, varsayılan olarak bağlı değildir, completebağlı olduğu, Tabvarsayılan olarak. Alternatif olarak, Esc *tüm dosyalar için tamamlamalar eklemek için kullanın ve komut satırından silmek istemediklerinizi kaldırın.
  • Zsh'de, varsayılan ayarlar iyidir; sahip olmanız setopt auto_menuveya setopt menu_completeayarlamanız gerekir .

Kabukunuzda tamamlama yardımcı rm -i -- *olmazsa, bu dosya dışında “hayır” ı arayabilir ve cevaplayabilirsiniz. Dosyanın adı yazdırılabilir bir karakterle başlamazsa, eşleşmeleri ilk karakteri yazdırılabilir karakter kümesinde olmayan dosyalarla sınırlayabilirsiniz:

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

(Deseniniz, bir seçenek olarak -fkabul rmedilecek bir dosyayla eşleşebilirse, dikkatli olun .)

Başka bir yöntem, ls -idosyanın inode'unu bulmak için çağrı yapmaktır (inode, verilen dosya sistemindeki bir dosyayı benzersiz bir şekilde tanımlamaktadır), sonra find -inumo dosya üzerinde çalışmaktadır. Bu yöntem çoğunlukla, dizin çok fazla dosya içerdiğinde yararlıdır.

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

Eğer senin findbir yok -deleteseçeneği çağrıyı rm:

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

(Evet, bunun çoğunun zaten yayınlandığını biliyorum. Ancak ilgili bilginin yanıtları bunu olması gerekenden daha karmaşık hale getiriyor.)


4

echo -eKarakteri almak için kullanmayı deneyin \177, sonra xargsgeçmek için rm. echoconvert böylece hex için, ondalık kaçar almaz: Turns dışarı 177sekizlik olduğu; önce echobir \0(değişmez, boş bayt değil) gerektirir :

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

\ Xb1 \ 0 \ 177 \ nin hex gösterimi olduğunu mu söylüyorsunuz?
Bay Moose

@MrMoose \xb1ondalık sayıdır 177, \0boş-sonlandığı onu ve -0anlatır xargsbir satır sonlandırılmış birinin yerine boş sonlandırılmış adını almaya.
Kevin

SunOS'ta bash kullanıyorum ve emrinizi denediğimde, xargs: illegal seçenek - 0 elde ettim. Man sayfasına baktım ve boş sonlandırma seçeneği göremedim. Şimdi sorun için bir çözüm bulmayı başardım. Cevap olarak işaretlenmiş cevaba bakınız.
Bay Moose

Siz echo, olduğu gibi, xargs dosyasına 2 dosya adı gönderir ve ardından rm... ikinci dosya adı ... olur \n. Bu, ya bir hataya yol açar ya da bu addaki bir dosyayı siler ('\ n')
Peter. Ey

@perer Evet, daha yeni farkettim. -nNewline'dan kurtulmayı ekledim .
Kevin

3

Sadece yaklaşık dosyası size garanti edemez yapar bir isim var. Sadece yazdırılamayan karakterler içeren bir ad olabilir.

Eğer rmiş vermedi, daha sonra çıktıyı kullanarak findile -inumbir argüman olarak seçeneğe rmyardımı olası değildir; sadece aynı argümanı rmaynı problemle geçecek .

Dosya bu dizindeki tek dosya değil mi?

Deneyeceğim ilk şey cddizine girip yazmak ve rm ./ardından Sekme tuşuna basmak. Bu, argümanı dosyanın asıl adına genişletmeli ve önceki dosya argümanı bir dosya adından başka bir şey olarak yorumlamayı ./engellemelidir rm.

Başka bir çözüm cdüst dizine gitmektir, sonra dizinde rm -r(ya da gerekirse rm -rf) kullanın . Bu, adı ne olursa olsun dizini ve tüm içeriğini kaldırmalıdır. Daha sonra mkdirdizini yeniden oluşturmak için kullanabilirsiniz (ve chmodizinlerini geri yüklemek için).

DÜZENLE :

ls -lbÇıktınıza tekrar baktığımda , dosya adının ASCII DELkarakteriyle (ölümcül olmayan kötü) başladığını ve bir veya daha fazla yeni satır karakteri (gerçekten kötü olan) içerdiğini düşünüyorum. Söyleyebileceğim kadarıyla, rmkomut bir yeni satırı dosya adının bir parçası olarak yorumlayamıyor.

Ancak unlink()sistem çağrısı yapabilir. İşte birlikte attığım ve şu anki dizindeki dosyalar arasında yinelenecek olan bir Perl betiği, her birini sizden kaldırmak isteyip istemediğinizi soracak. rmDosyaları kaldırmak gibi bir harici komut kullanmaz , bu nedenle dosya sisteminin desteklediği komik karakterleri (ASCII NULve dışındaki herhangi bir şey /) kullanabilmelidir.

İçeren dizini rm -rveya rm -rfdizinini yapmak yine de çalışmalıdır, ancak yalnızca tek bir dosyayı kaldırmak istiyorsanız bunu deneyebilirsiniz.

#!/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;
}

(Dizinde saklamak istediğiniz başka dosyalar varsa, başka bir çözüm, diğer tüm dosyaları geçici bir dizine taşımak, ardından dizini kopyalayıp yeniden oluşturmak ve diğer dosyaları geri taşımaktır.)

(Oh, ve bu dosyayı oluşturmak için ne yaptıysanız, bir daha yapmamayı deneyin!)


1

Komutu kullanarak tam olarak bu dosyayı bulabilirseniz find, -deleteyüklemeyi kullanabilirsiniz . Sadece dikkatli ol ve -deletefind komutunun son parametresini yap, yoksa çok acıtacak ...


1

Yakınsın. Adım adım, burada dosyayı inode numarasına göre silebilirsiniz.

İlk önce, kullanmak istediğiniz dosyanın inode numarasını bulun ls -li. Inode numarası, çıktının ilk sütununda olacaktır.

Örneğin:

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

Bu durumda, inode numarası 311010’dur.

findDosyayı inode numarasına göre aramak için kullanın .

find . -inum 311010 

Bunun findyalnızca silmek istediğiniz dosyanın adını döndürdüğünden emin olun . Örneğin:

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

Bunun finddoğru dosyayı bulduğundan emin olduktan sonra, -deleteparametreyi ile iletin find. Bu dosyayı sizin için siler.

find . -inum 311010 -delete

0

Diğer cevaplar harika ve neredeyse tüm ortamlarda çalışacak.

Ancak, çalışan bir GUI'niz varsa, dizini nautilus, dolphin, konqueror veya favori dosya yöneticinizde açın; birkaç fare tıklamasıyla birlikte çalışmayan bir adı olan herhangi bir dosyayı kolayca görüp silebilmelisiniz. .

Normal bir emac veya vim kullanıcısı değilseniz (diğer birkaç cevapta da belirtildiği gibi), bu gitmek için en kolay yol olabilir.


0

"\ 033" (gerçek "Kaçış" karakteri) adlı bir dosyada benzer bir sorun vardı.

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

Yukarıdakiler, geçerli bir dizinde bir harf veya rakam ile başlamayan dosyaları silmenizi isteyecektir.


0

Bunun yerine, geçerli dizini yeniden adlandırabilirsiniz DirX_OLD, adıyla yeni bir dizin oluşturmak DirXve gerekli tüm dosyaları taşımak DirX_OLDiçin DirX. Dosyaları kopyaladıktan sonra silebilirsiniz.DirX_OLD


0

Sadece kimseye yardım ederse diye iki kuruş değerimi ekleyeceğim. Dosya adlarını statbu şekilde joker karakter üzerinde kullanarak elde edebildim :

stat -c %N *

Çıktı:

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

Sonra dosyalara erişmek için ANSI C alıntı dizeleri (kabul edilen cevapta kullanıldığı gibi) kullanabilirim:

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

0

Her dosyanın bir adı vardır, tam olarak hangisini bulmanız gerekir.

Bu dosyaları örnek olarak kullanacağım:

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

Bu dosyalar ?normalde olduğu gibi gösterilecektir ls:

$ ls
??  ?  ?002  a  abc  b

Ancak ls, -Qseçeneğinize izin verirseniz , gerçek dosya adının ne olduğu açık olmalıdır:

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

bunlar inode numaraları ve 1pwd'deki dosyaların sütununda bulunan "Quoted" isimleridir .

Bu, genişletmeleri kullanmakta (globbing) bir (POSIX) kabuğunun kabiliyetini kullanıyor:

Yazdırılmayan karakterli adlara sahip olmak için:

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

Ve yalnızca yazdırılmayan karakterleri olabilecek dosyaları listelemek için :

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

Daha sonra, seçmeli ( -i(etkileşimli) seçeneği) kullanmak için bunları kaldırın:

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

Sadece yyukarıdaki soruya cevap vererek hangilerinin silineceğini seçmeniz gerekiyor .


0

Otomatik tamamlama özelliğine sahip bir bash varsa, bu sizin için işe yarayabilir. Dizin listesinde gösterilen karakteri yazdım. Sonra otomatik tamamlamayı tetikledim ve adı yazdırılabilir bir şey olarak yeniden adlandırdım.

İşte benim için çalıştı ne:

$ 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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.