FreeBSD: Verzeichnis namens ^ C (wirklich!) - Wie entferne ich?

127

Ich habe einen Tippfehler gemacht:

$ history
169 9:34    la /usr/local/etc/
170 9:35    sudo mkdir ^C
171 9:36    sudo mkdir /usr/local/etc/dnsmasq.d

Jetzt habe ich eine Datei mit dem Namen ^ C (Strg + C) !! Wenn ich benutze, lssehe ich nur ein Fragezeichen (wahrscheinlich aufgrund des Gebietsschemas?)

% ls -al
total 60
drwxr-xr-x  2 root   wheel    512 Jan 21 09:35 ?        <- this one
drwxr-xr-x  5 admin  wheel    512 Jan 21 16:24 .
drwxr-xr-x  3 root   wheel    512 Jan 20 14:29 ..
-rw-r--r--  1 admin  nobody  1114 Jan 20 19:10 .cshrc
-rw-------  1 admin  wheel   6002 Jan 21 15:27 .history
-rw-r--r--  1 admin  nobody   182 Jan 20 14:29 .login
-rw-r--r--  1 admin  nobody    91 Jan 20 14:29 .login_conf
-rw-------  1 admin  nobody   301 Jan 20 14:29 .mail_aliases
-rw-r--r--  1 admin  nobody   271 Jan 20 19:04 .mailrc
-rw-r--r--  1 admin  nobody   726 Jan 20 19:05 .profile
-rw-------  1 admin  nobody   212 Jan 20 14:29 .rhosts
-rw-r--r--  1 admin  nobody   911 Jan 20 19:06 .shrc
drwx------  2 admin  nobody   512 Jan 20 15:05 .ssh
drwxr-xr-x  2 admin  wheel    512 Jan 20 19:08 bin

und

% ls -i
3611537 ?   3611534 bin

Ich möchte diese Datei entfernen. Ich versuche mvund wenn ich die Tab-Vervollständigung benutze, zeigt es mir:

% mv
^C/  bin/

Offensichtlich kann ich kein ^ C: - / eingeben. Wie entferne ich diese Datei?

Mausy5043
quelle
11
Es ist schade, dass dsw es nicht in POSIX geschafft hat.
Mark Plotnick
12
@ MarkPlotnick: Schade, dass das Original dsw es nicht in POSIX geschafft hat.
Matteo Italia
4
Ich glaube nicht, dass Sie es Strg + C genannt haben, Sie haben es nach dem ASCII-Zeichen benannt, das dieser Tastenkombination zugeordnet ist, dh wahrscheinlich ETX (ASCII 3). Ihre Konsolenschrift hat keine Glyphe für dieses Zeichen, daher wird eine generische Substitutionsglyphe "?" Verwendet.
Jiggunjer
5
emacs -nw -f diredgibt einen Verzeichnisnavigator. <kbd> D </ kbd> löscht nach Bestätigung die Datei unter dem Cursor.
Thorbjørn Ravn Andersen
9
@ MatteoItalia Es ist schade, dass Steuerzeichen in Dateinamen und andere idiotische Ideen es in POSIX geschafft haben ...
Pipe

Antworten:

188

^V( ctrl+ v) fungiert als eine Art Escape-Sequenz für den nächsten Tastendruck und fügt den zugeordneten Wert ein, anstatt die normalerweise zugeordneten Aktionen auszuführen.

Wenn Sie dies verwenden, sollte ^V^C( ctrl+ v, ctrl+ c) funktionieren, um Ihren schwierigen Dateinamen in das Terminal einzugeben.

Håkan Lindqvist
quelle
41
Dies war wahrscheinlich, wie OP ihren Tippfehler an erster Stelle machte. V und C stehen auf der Tastatur direkt nebeneinander.
Stig Hemmer
14
Oder sie haben versucht, die Windows-Zwischenablage auf dem bsd-Terminal zu verwenden.
Joel Coel
2
@JoelCoel Gewohnheiten sterben nie!
Mafii
1
Interessanterweise ^V^Chat nicht funktioniert in der Zsh Zeileneditor; Das Quoted-Insert- Widget (Suche auf der Seite nach ^V) fügt explizit keine Interrupt-Zeichen ein. Jakobs Antwort (mit printf) ist möglicherweise eine portablere Möglichkeit, ein Steuerzeichen in einem Shell-Argument anzugeben.
Meilen
@StigHemmer: Was auch passieren kann, ist, dass Sie während eines Befehls Strg-C drücken, dies dann vergessen und den Befehl später kopieren und einfügen.
Mehrdad
89

Sie können die Datei auch mit inode entfernen:

$ ls -i1
290742 foo
293246 ^C
$ find . -inum 293246 -delete

Was auch immer Sie tun, um Gottes willen, stellen Sie nicht -deletevor -inum:

$ touch foo bar baz quux
$ find . -name '*u*' -delete
$ ls
bar baz foo
$ find . -delete -name 'b*'
find: `./baz': No such file or directory
find: `./bar': No such file or directory
$ ls
$ 

Herzlichen Glückwunsch, Sie haben gerade alle Ihre Dateien gelöscht. Bei findist die Reihenfolge der Argumente wichtig !

Bischof
quelle
2
Warum nicht -deletevorher stellen -inum? Ist dies nur eine Vorsichtsmaßnahme für den Fall, dass Sie die Eingabetaste vorzeitig drücken, oder hat die Reihenfolge der Argumente tatsächlich Einfluss auf das Ergebnis?
Detuur
10
@detuur: Reihenfolge beeinflusst Ergebnis. Siehe Bearbeiten.
Bischof
37
Geben Sie -deleteden Befehl erst ein, nachdem Sie den Befehl ausgeführt haben, ohne -deletezu überprüfen, ob der gewünschte Befehl gefunden wurde .
Kaz
2
@ Kaz wird nicht viel helfen mit dem Hinzufügen von -delete in der Mitte des Kommandos
RIAD
9
@Kaz mit -printstatt -deletemacht einen sehr guten Test.
Mark Ransom
32

Eine andere Option ist zu verwenden rm -ri ./*; rmwerden Sie vor dem Löschen einer Datei und eines Verzeichnisses gefragt, sodass Sie nur yauf die "fehlerhafte" Datei und nauf alle anderen antworten müssen .

In Ihrem Fall können Sie sogar die Anzahl der Antworten reduzieren rm -ri ./?, da Ihre "fehlerhafte" Datei nur ein Zeichen lang ist.

Matteo Italia
quelle
8
select f in ?; do rm -i "$f"; break; donehat alle Vorteile von -i, ohne die Qual, auf noführende unerwünschte Ereignisse antworten zu müssen oder fälschlicherweise Ja zu einem zu sagen, den Sie behalten möchten.
Bischof
6
Im Falle des OP ist es ein Verzeichnis, keine Datei. rmdir ?/entfernt alle leeren Einzelzeichenverzeichnisse und beschwert sich darüber, dass die anderen nicht leer sind.
Peter Cordes
2
@bishop: whoa, ich wusste gar nicht, dass selectes das gibt, ziemlich ordentlich!
Matteo Italia
@PeterCordes: Wops, ich habe nicht bemerkt, dass wir über Verzeichnisse sprechen; Ich habe zu meinen Beispielen hinzugefügt -r(und ./- es ist immer leicht zu vergessen), da rmdirdie -iFlagge leider nicht unterstützt wird . Trotzdem denke ich, dass in diesem Fall der beste Weg eine Kombination aus Bischof und Ihrem Kommentar wäre.
Matteo Italia
1
@MatteoItalia gibt es selectnur in einigen Shells, weshalb Sie wahrscheinlich nicht darauf gestoßen sind. Skripte und Lösungen, die portabel sein sollen, vermeiden dies, sodass wir es weniger wahrscheinlich "in the wild" sehen.
mtraceur
23

Eine Möglichkeit ist, den Dateinamen mit etwas anderem als nachzuschlagen ls. Wenn Sie wissen, dass es von einem wörtlichen Ctrl+ erzeugt wurde C, können Sie das ASCII-Zeichen anhand einer Tabelle mit Steuerzeichen oder mit einer benutzerfreundlicheren Oberfläche wie der von Python finden:

>>> import os
>>> os.listdir('.')
['\x03', ...]

Eine andere Möglichkeit wäre, einen hexadezimalen Speicherauszug der Ausgabe von lsz hexdump.

Dann können Sie die Datei mit (zum Beispiel) diesem Bash-Befehl löschen:

rmdir "$(printf '\x03')"

(Die doppelten Anführungszeichen werden nur benötigt, wenn sich das Zeichen, das Sie drucken möchten, in Ihrer IFSVariablen wie \x20oder \x0Abefindet. Es ist jedoch eine gute Angewohnheit, Befehlsersetzungen in Anführungszeichen zu setzen, es sei denn, Sie möchten, dass die Shell eine Feldaufteilung durchführt usw.)

Jakob
quelle
2
Auch cat -v(Plus man ascii) kann für den ersten Teil helfen.
Matteo Italia
13
... oder Sie verwenden os.rmdir('\x03')direkt aus der Python-Shell.
moooeeeep
15

In solchen Situationen ist es häufig einfach, ein Platzhaltermuster zu finden, das mit der entsprechenden Datei übereinstimmt.

In Ihrem Fall wäre dies einfach ?(Abgleichen aller Dateinamen mit genau einem Zeichen).

Überprüfen Sie einfach, ob es wirklich Ihren Wünschen entspricht:

ls -ld ?

Und dann das Verzeichnis entfernen:

rmdir ?

Sie können dies auch mit der Tab-Vervollständigung kombinieren . Du kannst Tippen

rmdir ?

und drücken Sie die Tabulatortaste, und z. B. in der Bash wird es durch ersetzt

rmdir ^C/

und Sie können dann die Eingabetaste drücken und es macht, was Sie wollen.

Jukka Suomela
quelle
11

Sie können Midnight Commander (mc) zum Löschen der Datei verwenden - wählen Sie sie einfach mit den Auf- / Ab-Tasten aus und drücken Sie F8.

Ich habe das gelegentlich gemacht, als Dateinamen aufgrund der Kodierung seltsame Zeichen hatten.

filo
quelle
4
Oder so ziemlich jeden anderen Dateimanager.
Stig Hemmer
@StigHemmer Natürlich können einige besser als andere bestimmte Dateinamen anzeigen. Wahrscheinlich könnte die Antwort erklären, warum MC eine optimale Wahl im Vergleich zu einigen ausgewählten anderen ist. Ich würde es nicht wissen, da ich es nie benutzt habe.
can-ned_food
7

Noch eine andere Möglichkeit: Verwenden Sie statdiese Option, um eine maskierte Darstellung des Verzeichnisnamens zu erhalten:

$ stat *|grep File:
  File: ‘\003’

Jetzt kennen Sie eine Darstellung des Dateinamens, sodass Sie die Datei nach Namen entfernen können, indem Sie Folgendes verwenden printf:

$ rmdir -v "$(printf '\003')"
rmdir: removing directory, ‘\003’

Wenn Sie Bash verwenden, können Sie Folgendes vermeiden printf:

$ rmdir -v $'\003'
rmdir: removing directory, ‘\003’
Ruslan
quelle
Übrigens, wenn die Shell bash ist, $'\x03'ist es einfacher als printf aufzurufen. Dasselbe gilt für FreeBSD sh, das über die POSIX-Shell mit einigen leckeren Funktionen erweitert wurde.
Netch
@Netch guter Punkt über Bash $'...', aber ich würde unnötige Konvertierung von Oktal in Hexadezimal im Allgemeinen vermeiden. Was wäre, wenn die Datei '\111'(in der statAusgabe) benannt wäre? Würden Sie es trotzdem mit entfernen $'\x49'? Verwenden statSie besser die gleiche Reihenfolge, die Sie angegeben haben: im Fall des OP rmdir $'\003'.
Ruslan
6

Eine Lösung, die für mich funktioniert hat, ist:

rm ./[Tab][Tab][Tab]...

um durch die verfügbaren Dateien zu blättern, bis ich die gefunden habe, die ich entfernen möchte.

Sie müssen jedoch die erforderlichen Einstellungen in Ihrer Shell haben, damit dies funktioniert.

joeytwiddle
quelle
^ C ist wirklich früh in der Tab-Sequenz, also +1 für dich.
Joshudson
5

Am einfachsten ist es, alles in das temporäre Verzeichnis zu verschieben und dann rm -r DIRNAME.

Kondybas
quelle
7
Scheint Ihnen das wirklich einfacher zu sein als die akzeptierte Antwort?
Küken
2
@chicks: Das ist eigentlich keine so schlechte Antwort. Ich habe gesehen, dass ^ V ^ C nicht funktioniert, damit jemand stecken bleibt.
Joshudson
Es ist an sich nicht falsch, aber es scheint eine Menge zusätzlicher Arbeit im Vergleich zu den direkteren Lösungen zu sein. Vielleicht bin ich von Linux verwöhnt, ^vhabe mich aber ewig durchgearbeitet.
Küken
6
@chicks ^Vbenötigen spezielle Kenntnisse, während das Verschieben von Dateien und das Entfernen des übergeordneten Verzeichnisses aus den Grundlagen abgeleitet werden kann.
Kondybas
5
Strg + V ist abhängig von Ihrer genauen Arbeitsumgebung gefährlich vieldeutig. Einige Terminalemulatoren können dies als Paste interpretieren. Wenn Ihr Einfügepuffer den Namen eines Elements enthält, das Sie nicht löschen möchten, und eine neue Zeile, liegt möglicherweise ein Problem vor.
Rackandboneman
1

Wenn es das einzige leere Verzeichnis ist (oder Sie keine Lust haben, andere leere Verzeichnisse zu entfernen), verwenden Siermdir */ . Es wird eine Fehlermeldung angezeigt rmdir, dass nicht leere Verzeichnisse nicht entfernt werden können, aber das ist in Ordnung. GNU rmdirunterstützt --ignore-fail-on-non-empty, oder Sie könnten 2>/dev/null.

Durch /das Nachstellen stimmt der Glob nur mit den Verzeichnisnamen überein.

Sie können im Voraus prüfen, welche leeren Verzeichnisse unter dem aktuellen mit vorhanden sind
find -maxdepth 1 -type d -empty -ls. (Und Sie können die ändern -ls, -deletewenn Sie möchten).

Sie können einen spezifischeren Glob-Ausdruck verwenden rmdir [^A-Za-z0-9._]/, um Verzeichnisse abzugleichen , die mit einem nicht alphanumerischen Dateinamen oder einem Unterstrich beginnen. Ich habe auch eingeschlossen ., aber Glob-Ausdrücke stimmen .sowieso nicht normal überein .


Wie bereits erwähnt, können Sie den Namen auf einzelne Zeichen mit einem Globus aus ?folgenden Elementen beschränken : rmdir ?/

rmdirKeine -iOption, wie es der Fall rmist, vermutlich, weil leere Verzeichnisse normalerweise nicht wertvoll sind und einfach neu erstellt werden können.

Peter Cordes
quelle
1
Sie möchten wissen, welche Verzeichnisse Sie neu erstellen möchten, und rmdirkönnen Ihnen mitteilen, ob Sie die -vOption an sie übergeben (zumindest in GNU).
Ruslan
@ Ruslan: Nicht, wenn Sie andere veraltete Verzeichnisse hätten, die Sie nicht mehr interessieren, und das Entfernen dieser Verzeichnisse wäre ein Bonus. Sie könnten nach leeren Verzeichnissen suchen mitfind -maxdepth 1 -type d -empty -ls
Peter Cordes
-1

Bevor Sie etwas riskantes unternehmen, versuchen Sie Folgendes:

rmdir -- ^C

Im Allgemeinen - ist ein Trennzeichen, das angibt, dass dem Befehl keine -o-Punkte folgen, aber es ermöglicht auch, dass seltsame Zeichen nicht als etwas anderes interpretiert werden.

Ein weiteres Anwendungsbeispiel ist whois -r -- "-r OBJECT-RIPE"

(-r ist eine Abkürzung für reif, aber im reifen whois auch ein Parameter)

Wenn es beim ersten Versuch nicht funktioniert, versuchen Sie es vielleicht rmdir -- "^C"

Aber in meiner csh-Shell brauche ich nichts davon, es rmdir ^Cfunktioniert einfach schon für mich.

Leo Vandew.
quelle
1
In csh rmdir tippen, gefolgt von <ctrl> C funktioniert? Ja wirklich?! Ich würde erwarten, dass es sich anders verhält, nämlich den rmdirBefehl abzubrechen und Sie zur Befehlszeile zurückzukehren.
Mausy5043
Es wird in der Tat. Lesen Sie die akzeptierte Antwort zur Eingabe eines ^ C-Zeichens in der Befehlszeile.
Ale