Hallo, On Tue, 15 Apr 2003, Jan Trippler wrote:
On Die, 15 Apr 2003 at 21:09 (+0200), Jan Trippler wrote:
Ich würde folgenden Ansatz angehen (ungetestet):
cnt=1 for file in "$@" ^^^^ da drin steht der aktuelle Dateiname. do new="$trash/`basename \"$1\"`-$$.$cnt" ^^ und deshalb ist das hier Quatsch! So muss es heißen: new="$trash/`basename \"$file\"`-$$.$cnt"
Apropos, u.a. an Patrice, so werden Variablen mit Dateinamen richtig gequotet ;) [..]
Bei der Gelegenheit habe ich gleich noch mal nachgedacht: Es kann ja immer noch sein, dass zufällig eine Datei gleichen Namens in trash existiert. Außerdem haben wir noch das Problem, dass der Anwender u. U. Verzeichnisse angibt. Deshalb ist folgender Ansatz besser:
cnt=1 for file in "$@" do if test -d "$file"; then echo "Verzeichnisse können nicht nach $trash verschoben werden" continue
¿Por qué? base="`basename \"$file\"`" if test -d "$file" then new="${trash}/${base}" while test -d "$new" do test $cnt -le 9999 || { echo "Fehler:...">&2; exit 1; } cnt=$((cnt+1)) new="${trash}/${base}-$$.$cnt" done
fi new="$trash/`basename \"$file\"`" while test -f "$new"; do cnt=`expr $cnt + 1` new="$trash/`basename \"$file\"`-$$.$cnt" done else while test -f "$new" do test $cnt -le 9999 || { echo "Fehler:...">&2; exit 1; } cnt=$((cnt+1)) new="${trash}/${base}-$$.$cnt" done fi
mv "$file" "$new" if [ $? -eq 0 ] ; then echo "$file wurde nach $new verschoben" else echo "Es konnte nicht gelöscht werden!" fi done
if mv -i "$file" "$new" ## ich will immer noch auf der sicheren Seite ## sein, falls es zu einer Namenskollision kommt then echo "$file wurde nach $new verschoben" else echo "Kann $file nicht in den Papierkorb verschieben" fi Ich hasse diese hirnrissige: befehl if befehl_der_prueft_ob_befehl_ok; then ... Entweder, ein Befehl gibt einen sinnvollen Exit-status zurueck, den muss man dann nicht auch noch mit 'test' ueberpruefen, um dann den Exit-status von 'test' auszuwerten. Das erinnert mich immer an "Von hinten durch die Brust ins Auge"... Oder, ein Befehl gibt keinen auswertbaren Exit-status zurueck, dann muss man den so oder so auswerten (da hilft dann auch $? genau gar nichts, da steht dann eh nur der nicht sinnvolle Exit-status drin), z.B. durch ein '|grep -q blubb' hintendran. Und das ergibt dann immer noch folgende Konstruktion: if befehl | grep -q blubb; then ... Fazit: $? ist in allen Faellen ueberfluessig, in denen man den Exit-status _nicht_ explizit einer benamsten Variablen zuweist oder z.B. mittels echo ausgibt. Folgendes illustriert diese beiten Ausnahmen, in denen $? sinnvoll ist: ==== befehl befehl_status="$?" case $befehl_status in 1) ...;; 2) ...;; *) ...;; esac exit $befehl_status ==== ==== ziemlich sinnfrei ==== error() { echo "$1 wurde mit Fehler beendet: exitcode: $2" >&2 } fatal() { error "$@" exit $2 } befehl || error "befehl" $? nochnbefehl || fatal "nochnbefehl" $? ====
Jetzt kann höchstens noch die while-Schleife bis zum MAXINT laufen und dann das Script abbrechen, aber wenn dieser Fall eintritt, läuft eh was schief ;-)
Ajup. s.o.
Und zu guter Letzt noch was: Dieser Mülleimer nutzt Dir wenig, wenn Du Dir nicht merkst, wie die Originalpfade der Dateien hießen (dann wird nämlich das Wiederherstellen ein ziemliches Rätselraten). Als schnelle Hilfe könntest Du eine Textdatei in trash hinterlegen, die den Originalpfad speichert:
[..]
Eine andere Alternative: Alle verschobenen Dateien werden mit ihrem Pfad verschoben (dann kann man das auch für Verzeichnisse erlauben - vorausgesetzt, sie liegen im gleichen Dateisystem):
cnt=1 for file in "$@" do if test -d "$file"; then newfn= newdn="$file" else newfn="`basename \"$file\"`" newdn="`dirname \"$file\"`" fi newdn="$trash`(cd \"$newdn\"; pwd)`"
*huch*[tm]. Da fehlt noch die Fehlerbehandlung, falls das cd fehlschlaegt... Und wozu die subshell? newdn="${trash}/`cd \"$newdn\" || exit -1; pwd -P`" ==== ~ (0)$ cd /opt/kde /opt/kde (0)$ x=bin/kcmjoy /opt/kde (0)$ f="`basename \"$x\"`" /opt/kde (0)$ d="`dirname \"$x\"`" /opt/kde (0)$ echo "$d $f" bin kcmjoy /opt/kde (0)$ n="/TRASH/`cd \"$d\" || exit -1; pwd -P`" /opt/kde (0)$ echo "$n" /TRASH//usr/local/opt/kde/bin /opt/kde (0)$ d="blubb" /opt/kde (0)$ n="/TRASH/`cd \"$d\" || exit -1; pwd -P`" bash: cd: blubb: No such file or directory /opt/kde (255)$ ==== Wie man sieht, werde ich weder ausgeloggt, und der exit-status (im prompt in den '()') ist ebenfalls korrekt ;)
while test -f "$newdn/$newfn"; do cnt=`expr $cnt + 1`
Was hast du eigentlich gegen $(( ))? Ja, $[] ist ein "bashism", aber $(( )) ist portabel "ueber" POSIX-shells. Allerdings nicht in bourne-shells. Aber die ash (die der bourne wohl recht nahe ist), kann auch das expr nicht, ist also egal ;) Die pdksh kann dagegen $(( )) und 'expr' aber nicht $[]. Oder gibt's ne (POSIX-)shell, die das expr kann, aber nicht das $(( ))? Ah, die tcsh kann expr, aber nicht $(( )), allerdings scheitert man da sowieso an den Variablenzuweisungen. Apropos shells: ich verwende das Teil auch viel zu selten, aber... ==== perlsh /home/dh: $ $x=1 perlsh /home/dh: $ $x=$x+2 perlsh /home/dh: $ echo $x 3 perlsh /home/dh: $ echo $x ** 2 9 perlsh /home/dh: $ cd "/opt/kde" perlsh /usr/local/opt/kde: $ use Cwd qw(abs_path) perlsh /usr/local/opt/kde: $ $x="bin/kcmjoy" perlsh /usr/local/opt/kde: $ echo abs_path($x) /usr/local/opt/kde/bin/kcmjoy ==== *bg* So Sachen wie das 'use Cwd qw(abs_path)' usw. kann man natuerlich in die config ("preload") aufnehmen, dann geht das ;) Allerdings ist die perlsh (ich hab' hier aber noch die vom 27.1.00) in Teilen noch recht unfertig und "alpha" oder so, und ob die noch ueberhaupt noch weiterentwickelt wird weiss ich auch nicht. Fuer Perlianer ist perlsh aber ein nettes Spielzeug statt 'perl -e' ;)
Warum nun dieser Aufwand zum Erzeugen von $newdn? Damit kriegt man - egal wie das Ausgangsargument aussieht - einen sauberen absoluten Pfadnamen hin: jan@k500:~> mkdir tmp/dir\ mit\ leer jan@k500:~> x=../jan/tmp/dir\ mit\ leer/abc jan@k500:~> newdn="`(cd \"\`dirname \\\"$x\\\"\`\"; pwd)`" jan@k500:~> echo $newdn /home/jan/tmp/dir mit leer
*g* -dnh PS: Jan, solle' mer mal unsere "fiesen" Dateinamen sammeln und als tarball wo ablegen? -- WANTED: Schroedingers Cat, dead or alive.