Wie kann ich eine Datei in ein Bash-Skript kopieren und beim Kopieren umbenennen und im selben Verzeichnis ablegen?

7

Wie würde ich eine Datei "file.doc" kopieren und beim Kopieren in "file_copy.doc" umbenennen und im selben Verzeichnis ablegen?

Und das nur, indem Sie das Skript aufrufen und den Dateinamen in das Argument einfügen:

bash launch_copyer file.doc
Redaktion
quelle
Wenn Sie nicht auf Bash bestehen, gibt es meiner Meinung nach auch dafür fertige Tools.
0xC0000022L
Vielleicht bin ich es nur, aber ich finde den Wortlaut hier wirklich verwirrend. Warum mvund cpunzureichend? Könnten wir ein Beispiel haben?
Anko

Antworten:

4

Hier ist keine Notwendigkeit erforderlich bash, eine Standard- shInterpreter-Implementierung reicht aus:

#! /bin/sh -
ret=0
for file do
  dir=$(dirname -- "$file")
  case $dir in
    (*[!/]*) dir=$dir/ # handle / and // specially
  esac
  base=$(basename -- "$file")
  name=${base%.*}
  name=${name:-$base} # don't consider .bashrc the extension in /foo/.bashrc
  ext=${base#"$name"}
  new_file=$dir${name}_copy$ext
  cp -- "$file" "$new_file" || ret=$?
done
exit "$ret"

(setzt voraus, dass die Datei- und Verzeichnisnamen nicht mit Zeilenumbrüchen enden).

(natürlich, das wird auch die Arbeit mit , bashda bashist einer dieser Standard shDolmetscher .)

Für eine bashspezifische Lösung können Sie Folgendes versuchen:

#! /bin/bash -
ret=0
re='^((.*/)?[^/])(([^/]*)(\.))?([^/]*)/*$'
for file do
  if [[ $file =~ $re ]]; then
    if [[ ${BASH_REMATCH[5]} ]]; then
      suffix=_copy.${BASH_REMATCH[6]}
    else
      suffix=${BASH_REMATCH[6]}_copy
    fi
    cp -- "$file" "${BASH_REMATCH[1]}${BASH_REMATCH[4]}$suffix" || ret=$?
  else
    printf >&2 '%s\n' "$0: Error: refusing to copy $file"
    ret=1
 fi
done
exit "$ret"
Stéphane Chazelas
quelle
Wie bei mir scheint dies auch zu scheitern, wenn die Datei keine gepunktete Erweiterung hat
Roaima
1
@roaima, nun, es wollte das ansprechen, aber es gab einen Tippfehler. Sollte jetzt funktionieren. Es ist auch Adressen Dinge wie foo.d/bar, foo/.bashrc, /foorichtig , die auch Lösung nicht ...
Stéphane Chazelas
2

Da fragt das OP nach einer Bash-Lösung. Hier ist eine, die es tut.

#!/bin/bash

if [[ ! -f $1 && $(($# != 1)) ]]; then 
    printf '%s\n' "Provide a filename"
    exit 1
fi

inFile="$1"
fileExt="${1#*.}"
destFile="${1%.*}"

cp -- "$inFile" "${destFile}_copy.$fileExt"  # As suggested, so the files that start with a dash are not ignored.
Valentin Bajrami
quelle
1
Dass in einer Reihe von Fällen wie diesen Argumenten scheitern: -foo-, foo.tar.gz, /foo/bar, foo.d/bar.doc. Ich bin mir nicht sicher, warum Sie darauf bestehen, dass das Argument eine reguläre Datei oder ein Symlink zu einer regulären Datei ist. Dies ist nicht Teil der Anforderung. Fehlermeldungen sollten auf stderr angezeigt werden.
Stéphane Chazelas
1
@ StéphaneChazelas Du hast da einen Punkt. Ich hätte das --Ende der Optionen angeben sollen. Nun, das .docschlägt eine Datei vor. Diese Überprüfung ist auch nicht unbedingt.
Valentin Bajrami
@ StéphaneChazelas das ist in der Tat noch kürzer. Gut zu wissen.
Valentin Bajrami
1
#!/bin/bash
ss=0
for file do
    cp -fp -- "$file" "${file%.*}_copy.${file##*.}" || ss=$?
done
exit $ss

Dies schlägt fehl, wenn filekein Punkterweiterungsteil vorhanden ist. Wenn Sie dies benötigen, verwenden Sie die Lösung von Stéphane Chazelas .

Roaima
quelle
Dadurch werden keine Dateien kopiert, die wie oben -fooerwähnt mit einem Bindestrich beginnen .
Holasz
@holasz hat das behoben. Ich habe nicht vor, Punkt-Erweiterungsdateien zu reparieren.
Roaima
0
cp /example/directory/file.doc /example/directory/file_copy.doc

Dies gibt den Dateinamen an und macht, was Sie wollen

user115967
quelle
Das hat OP auch nicht gefragt. Es kopiert einfach die Quelldatei in die Zieldatei. Es gibt jedoch einen kürzeren Schritt. cp /path/to/dir/{file.doc,file_copy.doc} Wieder auf die OP wan'ts die Positionsparameter verwenden$1
Valentin Bajrami
@ val0x00ff, eher wie cp /path/to/dir/file{,_copy}.dochier.
Stéphane Chazelas
0

Versuche dies:

#!/bin/bash
if [ -f "$1" ];
then
  cp -v "$1" _"$1"
  rename -v 's/_(.+?)\./$1_copy\./' _"$1"
fi

Das Skript prüft, ob die als Eingabe empfangene Eingabedatei vorhanden ist. In diesem Fall erstellt es eine temporäre Kopie der Datei und benennt diese Kopie dann um, wobei der erste Punkt in seinem Namen durch die Zeichenfolge ersetzt wird_copy.

Ich hoffe es ist was du brauchst.

Alfredo Capobianchi
quelle