Linux: Datei umbenennen, aber Erweiterung beibehalten?

10

Unter Windows / DOS kann ich sagen rename myfile.* yourfile.*, den Namen zu ändern, aber die Erweiterung beizubehalten. Wie wird das unter Linux erreicht?

Die Manpage schlägt nur vor, wie man die Erweiterung ändert, aber das ist das Gegenteil von dem, was ich will.

Bonus:
Ich möchte das Erstellungsdatum eines Fotos in seinen Dateinamen einfügen, um so etwas zu erhalten 20091231 2359 New Year.jpg. Ich fürchte, ich brauche eine nicht triviale Kombination von Befehlen, um das zu erreichen?

Torben Gundtofte-Bruun
quelle

Antworten:

14

Hier ist eine Antwort auf die Bonusfrage.

Ich möchte das Erstellungsdatum eines Fotos in seinen Dateinamen einfügen, um so etwas wie 20091231 2359 New Year.jpg zu erhalten. Ich fürchte, ich brauche eine nicht triviale Kombination von Befehlen, um das zu erreichen?

Angenommen, Sie möchten das Erstellungsdatum des Fotos aus den EXIF-Daten übernehmen, benötigen Sie dafür ein separates Tool. Glücklicherweise stellt sich heraus, dass jheaddies mit seiner -nOption eine triviale Möglichkeit bietet, genau das zu tun, was Sie wollen .

$ jhead -h
 [...]

 -n[format-string]

             Rename files according to date.  Uses exif date if present, file
             date otherwise.  If the optional format-string is not supplied,
             the format is mmdd-hhmmss.  If a format-string is given, it is
             is passed to the 'strftime' function for formatting
             In addition to strftime format codes:
             '%f' as part of the string will include the original file name
             [...]

Hier ist ein Beispiel:

$ jhead -n%Y-%m-%d-%f New_year.jpg   
New_year.jpg --> 2009-12-31-New_year.jpg

Bearbeiten : Um dies für ein paar Fotos zu tun, wäre es natürlich so etwas wie:

$ for i in *jpg; do jhead -n%Y-%m-%d-%f $i; done

Schauen Sie sich date --helpzum Beispiel die Ausgabe von an , um die Datumsformatierung nach Ihren Wünschen anzupassen . Es werden die verfügbaren Formatcodes aufgelistet.

(jhead ist für verschiedene Systeme weit verbreitet. Wenn Sie z. B. Ubuntu oder Debian verwenden, geben Sie einfach ein sudo apt-get install jhead, um es zu installieren.)

Jonik
quelle
1
Ich hatte nicht an Jhead gedacht, sondern nur an eine hässliche Kombination aus Umbenennen, Statistik und Schnitt. Vielen Dank für die tolle Antwort!
Torben Gundtofte-Bruun
10

Nur für den Umbenennungsteil funktioniert das Programm "Umbenennen". Es ist das gleiche wie das Beispiel, das Sie auf der Manpage gesehen haben, nur umgeschaltet.

justin@eee:/tmp/q$ touch myfile.{a,b,c,d}
justin@eee:/tmp/q$ ls
myfile.a  myfile.b  myfile.c  myfile.d
justin@eee:/tmp/q$ rename -v s/myfile/yourfile/ myfile.*
myfile.a renamed as yourfile.a
myfile.b renamed as yourfile.b
myfile.c renamed as yourfile.c
myfile.d renamed as yourfile.d
justin@eee:/tmp/q$ ls
yourfile.a  yourfile.b  yourfile.c  yourfile.d
justin@eee:/tmp/q$ 
user23307
quelle
1
In einigen Distributionen wird dieses Perl-Umbenennungsprogramm als Vorname bezeichnet.
Camh
Das ist wirklich nützlich! Ich war überrascht, wie viele dieser Arten von Fragen ich durchsuchen musste, bevor ich "Umbenennen" fand. Vielen Dank.
Alanning
7
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: yourfile.*: No such file or directory   
myfile.a    myfile.b
betelgeuse:tmp james$ for file
> in myfile.*
> do
> mv "${file}" "`echo $file | sed 's/myfile\./yourfile./'`"
> done
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: myfile.*: No such file or directory
yourfile.a  yourfile.b

Der Schlüssel ist, dass, wenn Sie ein Beispiel gesehen haben, das zeigt, wie ein Teil des Dateinamens mit einem regulären Ausdruck versetzt wird, dies das einzige Beispiel ist, das Sie benötigen. Erweiterungen haben auf Unix-Dateisystemen keinen besonderen Status - sie sind nur ein Teil des Dateinamens, der zufällig nach einem .Zeichen steht.

James Polley
quelle
1
Dies ist die Antwort auf meine Frage. (Aber die andere Antwort bringt mich schneller und einfacher dorthin.)
Torben Gundtofte-Bruun
4
Keine Notwendigkeit zu gabeln + ausführen : mv "$file" yourfile"${file#myfile}". Funktioniert mit jeder modernen Bourne-ähnlichen Shell (oder jeder POSIX-Shell), aber wahrscheinlich nicht mit der eigentlichen Bourne-Shell.
Chris Johnsen
4

Hier sind einige weitere Möglichkeiten, um Dateinamen zu bearbeiten

for f in *.jpg
do
    mv "$f" "before_part${f%.*}after_part.${f##*.}"
    # OR mv "$f" "before_part$(basename "$f" ".jpg")after_part.jpg"
done

Die Parametererweiterungen im mvBefehl funktionieren wie folgt:

${f%.*}- Löschen Sie das kürzeste übereinstimmende Muster vom Ende der darin enthaltenen Zeichenfolge $f. In diesem Fall löschen Sie alles nach und einschließlich des letzten Punkts. Die Single %bedeutet "am kürzesten vom Ende".

${f##*.}- Löschen Sie das längste übereinstimmende Muster vom Anfang der darin enthaltenen Zeichenfolge $f, in diesem Fall alles vor und einschließlich des letzten Punkts (dies schließt auch alle anderen Punkte ein). Das double #( ##) bedeutet "am längsten von Anfang an".

So zum Beispiel, wenn $f"Foo.bar.baZ.jpg" enthält:

echo "${f%.*}"

gibt

Foo.bar.baZ

und

echo "${f##*.}"

gibt

jpg

Der mvBefehl würde also nach seiner Erweiterung folgendermaßen aussehen:

mv "Foo.bar.baZ.jpg" "before_partFoo.bar.baZafter_part.jpg"
Bis auf weiteres angehalten.
quelle
Ich habe tatsächlich die FOR-Schleife verwendet, aber nicht das MV-Beispiel, weil ich es nicht verstehe :-)
Torben Gundtofte-Bruun
Hinweis: Die Bedeutung dieser f%und f##werden hier beschrieben, zum Beispiel: tldp.org/LDP/abs/html/parameter-substitution.html
Torben Gundtofte-Bruun
3

Unter Linux gibt es keine Dateinamenerweiterungen.

Verwenden Sie reguläre Ausdrücke, um bestimmte Teilzeichenfolgen aus dem Dateinamen auszuschneiden und darauf zuzugreifen.

Beispiel:

Reales Szenario: Sie extrahieren HTML aus einer CHM-Datei. Bei Dateinamen in Windows wird die Groß- und Kleinschreibung nicht berücksichtigt, sodass unter Linux fehlerhafte Links angezeigt werden. Sie haben eine Datei mit dem Namen index.HTML , aber href = "index.html" in URLs. Ihr Ziel ist es also, Dateinamen so anzupassen, dass sie mit Links verknüpft sind.

Angenommen, Sie haben den Dateinamen in einer Variablen:

FILENAME='index.HTML'

Ab Version 3.0 unterstützt bash selbst reguläre Ausdrücke, sodass Sie keine zusätzlichen Tools wie grep / sed / perl usw. benötigen, um Zeichenfolgen zu bearbeiten. Das folgende Beispiel zeigt das Ersetzen einer Back-End-Übereinstimmung in einer Zeichenfolge:

echo ${FILENAME/%\.HTML/.html}

Die Übereinstimmungs- und Ersetzungszeichenfolgen können auf Wunsch parametrisiert werden. Dies bietet zusätzliche Flexibilität beim Schreiben von Skripten. Das folgende Codefragment erreicht das gleiche Ziel:

match='\.HTML'
replacement='.html'
echo ${FILENAME/%$match/$replacement}

Weitere Informationen finden Sie in den Bash-Dokumenten.

Geek
quelle
1
Gibt es ein Beispiel für diese regulären Ausdrücke?
Gnoupi
+1. Diese Antwort ist jetzt (nach der Bearbeitung) sehr nützlich - ich hatte keine Ahnung, dass Sie eine solche String-Manipulation in Bash durchführen können.
Jonik
In der Tat jetzt viel besser, mit Beispielen. +1
Gnoupi
0

Hier ist ein anderes:

find -name "*.jpg" -printf '"%p" "%h/%TY%Tm%Td %TH%TM %f"\n' | while read -r f
do
    eval "mv ${f}"
done
Bis auf weiteres angehalten.
quelle
0

Es gibt immer mehr als einen Weg, dies zu tun. Ich habe das folgende Skript als / usr / local / bin / mrename eingefügt.

Geben Sie dann in das Skript mit den Fotodateien einfach Folgendes ein: mrename

Es gibt auch eine optionale auskommentierte Funktion im Skript zum Skalieren der Fotos (mit ImageMagick).

Hoffe, das ist nützlich für einige Leute.

#!/usr/bin/perl
#
# mrename files
#
#
use strict;

# if no 2 args, use defaults
my $dir = ".";

# read in path from command line
$dir = $ARGV[0] if ( defined( $ARGV[0] ) && $ARGV[0] ne "" );

# read in directory contents
opendir( DIR, $dir );
my @files = readdir( DIR );
closedir( DIR );

# rename and/or scale each file in directory
my $number_of_files = scalar( @files );
my $curfile = 0;

foreach my $file( @files ) {
    # only rename and scale jpg/gif files
    if ( $file =~ /\w+\.(jpg)$/ ) {
        my $extension = $1;
        $extension =~ tr/A-Z/a-z/;
        my $full_filename = "$dir/$file";

        # get stats on file- specifically the last modified time
        (my $dev,my $ino,my $mode,my $nlink,my $uid,my $gid,my $rdev,my $size,
        my $atime,my $mtime,my $ctime,my $blksize,my $blocks) = stat($full_filename);

        # convert last-modified time from seconds to practical datetime terms
        (my $sec,my $min,my $hour,my $mday,my $mon,my $year,my $wday,my $yday,
        my $isdst) = localtime($mtime);

        ++$mon;
        $year += 1900;

        my $filecdate = sprintf( "m%04i%02i%02i_%02i%02i%02i.$extension", $year, $mon, $mday, $hour, $min, $sec );
        my $full_newfilename = "$dir/$filecdate";

        # to scale files, use imagemagick by using the command below instead of mv 
        #my $cmd = "convert $full_filename -resize $scale% $full_newfilename";
        my $cmd = "mv $full_filename $full_newfilename";
        system( $cmd );

        # update percentage done
        my $percent_done = sprintf( "%5.2lf", 100* (++$curfile) / $number_of_files );
        print "\r$percent_done%";
    }
}
print "\n";

quelle
0

Sie können die -X/--keep-extensionOption mit rename(Version 1.600) verwenden:

-X, --keep-extension Save and remove the last extension from a filename, if there is any. The saved extension will be appended back to the filename at the end of the rest of the operations.

rename ist für Mac von Homebrew und für Linux von Linuxbrew erhältlich (neben anderen Installationsoptionen natürlich).

John
quelle