Ich möchte mehrere c-Quelldateien in einem Verzeichnis kopieren und umbenennen.
Ich kann so kopieren:
$ cp *.c $OTHERDIR
Aber ich möchte allen Dateinamen ein Präfix geben:
file.c --> old#file.c
Wie kann ich das in 1 Schritt machen?
Ich möchte mehrere c-Quelldateien in einem Verzeichnis kopieren und umbenennen.
Ich kann so kopieren:
$ cp *.c $OTHERDIR
Aber ich möchte allen Dateinamen ein Präfix geben:
file.c --> old#file.c
Wie kann ich das in 1 Schritt machen?
Antworten:
eine for
Schleife:
for f in *.c; do cp -- "$f" "$OTHERDIR/old#$f"; done
Ich füge oft die -v
Option hinzu, cp
damit ich den Fortschritt verfolgen kann.
Sie können Shell Globbing verwenden:
for f in *.c; do cp -- "$f" "$OTHERDIR/old#$f"; done
Das for variable in GLOB
Format erweitert den Glob auf alle übereinstimmenden Dateien / Verzeichnisse (mit Ausnahme der versteckten) und iteriert über diese, wobei jede nacheinander als $variable
(im obigen Beispiel $f
) gespeichert wird . Der Befehl, den ich zeige, durchläuft also alle nicht versteckten Dateien, kopiert sie und fügt das Präfix hinzu.
cd /foo/bar/; for f in *c
oder verwenden for f in /foo/bar/*.c; do name=${f##*/} ...
oder name=$(basename "$f")
.
Noch ein anderer Weg:
for f in $(find dir/ -type f | grep -v 'bk_'); do cp -- "$f" "$(dirname $f)/bk_$(pwgen -s 4 1)_$(basename $f)"; done
Jedes Mal, wenn Sie auf diese Weise laufen, wird dir / from geändert:
dir/foo/foo.c
dir/bar/bar.c
dir/baz/baz.c
In:
dir/foo/foo.c
dir/foo/bk_R3pP_foo.c
dir/bar/bar.c
dir/bar/bk_o1JD_bar.c
dir/baz/baz.c
dir/baz/bk_0QqF_baz.c
Und dann:
dir/foo/foo.c
dir/foo/bk_R3pP_foo.c
dir/foo/bk_dV06_foo.c
dir/bar/bar.c
dir/bar/bk_o1JD_bar.c
dir/bar/bk_B68i_bar.c
dir/baz/baz.c
dir/baz/bk_0QqF_baz.c
dir/baz/bk_p6P3_baz.c
Und dann...:
dir/foo/foo.c
dir/foo/bk_R3pP_foo.c
dir/foo/bk_dV06_foo.c
dir/foo/bk_2Ar8_foo.c
dir/bar/bar.c
dir/bar/bk_o1JD_bar.c
dir/bar/bk_B68i_bar.c
dir/bar/bk_wX7Z_bar.c
dir/baz/baz.c
dir/baz/bk_0QqF_baz.c
dir/baz/bk_p6P3_baz.c
dir/baz/bk_fPd3_baz.c
.. und so weiter.
find
die Ausgabe . Verwenden Sie grep
diese Option nicht , um Dateinamen auszuschließen, wenn dies find
alleine möglich ist.
Hier ist, wie man es bei Bedarf rekursiv machen würde:
for f in `find . -name \*.c`; do name="${f//\.\//__}"; fileName="${name//\//_}" ; echo "Copying $f as $OTHERDIR/old#$fileName"; cp -- "$f" "$OTHERDIR/$fileName"; done
find
die Ausgabe
Hier ist ein Einzeiler mit xargs
, tr
und Globbing. Könnte einen Wert haben.
echo *.c | tr ' ' '\n' | xargs -n1 -I{} cp "{}" "PREFIX{}"
Dies gibt alle übereinstimmenden Dateien *.c
als durch Leerzeichen getrennte Zeichenfolge zurück. Als nächstes werden tr
die zusätzlichen Leerzeichen in Zeilenumbrüche umgewandelt ( NB hat Dateinamen nicht mit Leerzeichen ** getestet). Wird xargs
dann mit jedem Dateinamen gefüllt und cp
mit dem entsprechenden Namen und Präfix ausgeführt.
*.c
kann für andere nützliche Globs geändert werden. Andere Präfixe im Teil xargs
und cp
können ebenfalls verwendet werden.
(erfordert find
Unterstützung -print0
) Ähnlich wie oben können wir find
eine durch Null getrennte Liste von Dateien ausgeben und xargs
mit einem Flag optimieren , um bei Null zu trennen
find . -name '*.c' -print0 | xargs -0 -n1 -I{} cp "{}" "PREFIX{}"
for f in /foo/bar/*.c
,$f
wird der gesamte Pfad enthalten, stattdessen nur der Name der Datei. Wie kann ich nur den Namen der Datei erhalten?