Wer kann mir eine logische Erklärung zu diesem Problem geben:
Ich kann diesen Befehl nicht ausführen:
sudo cp /data/*20150522* /backup/
cp: cannot stat `/data/*20150522*': No such file or directory
Und wenn ich zu Root wechsle, funktioniert es problemlos.
Ich bin sicher, dass es darum geht, die richtigen Berechtigungen zu haben, um die Dateien im /data-Verzeichnis aufzulisten, die über die folgenden Zugriffsberechtigungen verfügen:
drwxrwx--- 1 root root
Aber hier führe ich den Befehl mit sudo aus. Wo liegt also hier das Problem?
Antwort1
Die Shell versucht, das Glob-Muster zu erweitern, bevor sie das erweiterte Ergebnis an übergibt cp
(tatsächlich übergibt sie das Ergebnis an , sudo
das es dann unverändert an übergibt cp
). Da die Shell (sie wird als Sie und nicht als Root ausgeführt) das Verzeichnis nicht durchlaufen kann, cp
erhält sie schließlich das nicht erweiterte Muster in ihrer Argumentenliste.
cp
führt selbst keine Glob-Erweiterung durch. Es erwartet eine Liste von Dateinamen. Der String mit dem Muster darin benennt keine Datei.
Der vielleicht einfachste Weg, die Aufgabe auszuführen, besteht darin, Ihren Befehl in einer Sub-Shell aufzurufen. Setzen Sie den Befehl entweder in doppelte Anführungszeichen ( "
) oder in einfache Anführungszeichen ( '
).
sudo sh -c "cp /data/*20150522* /backup/"
sudo sh -c 'cp /data/*20150522* /backup/'
Dies funktioniert, weil die Sub-Shell das Glob-Muster in der Befehlszeichenfolge erweitert, bevor der Befehl aufgerufen wird. Da die Sub-Shell unter als Root ausgeführt wird sudo
, ist die Erweiterung erfolgreich.
Wenn Sie den Befehl in Anführungszeichen in die untergeordnete Shell setzen, kann die übergeordnete Shell Shell-Variablen erweitern, bevor der sudo
Befehl aufgerufen wird. Wenn Sie möchten, dass Variablen von der untergeordneten Shell erweitert werden, sollten Sie stattdessen einfache Anführungszeichen verwenden. In diesem Fall ist dies gleichwertig, da Sie keine Variablen haben. Sie können jedoch eine hinzufügen, um den Unterschied im Verhalten zu sehen.
sudo sh -c "echo $USER; cp /data/*20150522* /backup/"
sudo sh -c 'echo $USER; cp /data/*20150522* /backup/'
Der erste Befehl zeigt Ihren Benutzernamen an, während der zweite Befehl den Root-Benutzernamen anzeigt.