Linux: dosyayı yeniden adlandırın ama uzantıyı koruyun?


10

Windows / DOS'ta, rename myfile.* yourfile.*adı değiştirmek ama uzantı tutmak için söyleyebilirim . Linux'ta bu nasıl başarılır?

Man sayfası yalnızca uzantıyı nasıl değiştireceğinizi önerir, ancak bu istediğimin tam tersidir.

Bonus:
Aslında bir fotoğrafın oluşturulma tarihini dosya adına koymak istiyorum 20091231 2359 New Year.jpg. Korkarım, bunu başarmak için önemsiz bir komut kombinasyonuna ihtiyacım var mı?

Yanıtlar:


14

İşte bonus soru için bir cevap.

Aslında 20091231 2359 Yeni Yıl.jpg gibi bir şey elde etmek için fotoğrafın oluşturulma tarihini dosya adına koymak istiyorum. Korkarım, bunu başarmak için önemsiz bir komut kombinasyonuna ihtiyacım var mı?

Fotoğrafın oluşturulma tarihini EXIF ​​verilerinden almak istediğinizi varsayarsak, bunun için ayrı bir araca ihtiyacınız olacaktır. Neyse ki jhead, -nseçeneği ile tam olarak ne istediğinizi yapmak için önemsiz bir yol sunuyor .

$ 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
             [...]

İşte bir örnek:

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

Düzenleme : Tabii ki, bunu bir grup fotoğraf için yapmak, şöyle bir şey olurdu:

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

Tarih biçimlendirmesini beğeninize göre değiştirmek date --helpiçin örneğin; mevcut format kodlarını listeler.

(jhead farklı sistemler için yaygın olarak bulunur. Örneğin Ubuntu veya Debian kullanıyorsanız, sudo apt-get install jheadyüklemek için yazmanız yeterlidir .)


1
Jhead'i düşünmemiştim, sadece yeniden adlandırma, stat ve kesimin çirkin bir kombinasyonunu. Harika cevap için teşekkürler!
Torben Gundtofte-Bruun

10

Sadece yeniden adlandırma kısmı için, 'yeniden adlandırma' programı çalışacaktır. Man sayfasında gördüğünüz örnekle aynı, sadece değişti.

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$ 

1
Bazı dağıtımlarda bu perl yeniden adlandırma programına prename adı verilir.
camh

Bu gerçekten faydalı! "Yeniden adlandır" bulmadan önce bu tür sorulardan kaçını araştırmam gerektiğine şaşırdım. Teşekkür ederim.
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

Anahtar şudur: Dosya adının bir kısmının normal ifadeyle nasıl sıkıştırılacağını gösteren bir örnek gördüyseniz, ihtiyacınız olan tek örnek budur. Uzantıların unix dosya sistemlerinde özel bir durumu yoktur - bunlar dosya adının bir .karakterden sonra olan bir parçasıdır .


1
Sorumun cevabı bu. (Ama diğer cevap beni oraya daha hızlı ve daha kolay
getiriyor

4
Çatal + exec gerek yok sed: mv "$file" yourfile"${file#myfile}". Herhangi bir modern Bourne benzeri kabuk (veya herhangi bir POSIX kabuğu) üzerinde çalışır, ancak gerçek Bourne kabuğu üzerinde değil.
Chris Johnsen

4

Dosya adlarını işlemenin birkaç farklı yolu

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

Parametre açılımları içinde mvkomut çalışmaları şöyle:

${f%.*}- İçindeki dizenin sonundaki en kısa eşleşen deseni $fsilin, bu durumda son noktadan sonra ve son nokta dahil her şeyi silin. Tek %"sondan en kısa" anlamına gelir.

${f##*.}- İçindeki dizenin başlangıcından en uzun eşleşen deseni silin, $fbu durumda son noktadan önce ve son nokta dahil her şey (buna başka noktalar da dahil). Double #( ##) "baştan en uzun" anlamına gelir.

Örneğin, $f"Foo.bar.baZ.jpg" içeriyorsa:

echo "${f%.*}"

verir

Foo.bar.baZ

ve

echo "${f##*.}"

verir

jpg

Böylece, mvkomut bir kez genişletildiğinde şöyle görünecektir:

mv "Foo.bar.baZ.jpg" "before_partFoo.bar.baZafter_part.jpg"

Aslında FOR döngü kullanarak sona erdi ama MV örnek değil çünkü ben bunu anlamadım :-)
Torben Gundtofte-Bruun

Not: Bunların anlamı f%ve f##burada açıklanmıştır, örneğin: tldp.org/LDP/abs/html/parameter-substitution.html
Torben Gundtofte-Bruun

3

Linux'ta dosya adı uzantısı yok.

Dosya adından belirli alt dizeleri kesmek ve bunlara erişmek için normal ifadeleri kullanın.

Misal:

Gerçek hayat senaryosu: Bir chm dosyasından html ayıklıyorsunuz. Windows'daki dosya adları büyük / küçük harfe duyarlı değildir, bu nedenle Linux'ta bozuk bağlantılar alırsınız. URL'lerde index.HTML adında bir dosyanız var , ancak href = "index.html" var . Amacınız dosya adlarını bağlantılara uyacak şekilde uyarlamaktır.

Bir değişkente dosya adına sahip olduğunuzu varsayın:

FILENAME='index.HTML'

Sürüm 3.0 bash ile başlayan düzenli ifadeleri kendisi destekler, bu nedenle dize manipülasyonu gerçekleştirmek için grep / sed / perl vb gibi ek araçlara ihtiyacınız yoktur. Aşağıdaki örnek, bir dizede arka uç eşleşmesinin değiştirilmesini gösterir:

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

Eşleşme ve değiştirme dizeleri istenirse parametrelendirilebilir, bu komut dosyası yazarken ek esneklik sağlar. Aşağıdaki kod snippet'i aynı hedefe ulaşır:

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

Ek bilgi için bash belgelerine bakın.


1
Bu düzenli ifadelere herhangi bir örnek var mı?
Gnoupi

+1. Bu cevap şimdi (düzenleme sonra) çok yararlı - Bash böyle dize manipülasyon yapabileceğiniz hakkında hiçbir fikrim yoktu.
Jonik

Gerçekten de, örneklerle şimdi çok daha iyi. +1
Gnoupi


0

Bunu yapmanın her zaman birden fazla yolu vardır. Aşağıdaki betiği / usr / local / bin / mrename olarak koydum.

Sonra fotoğraf dosyalarını içeren komut dosyasına şunu yazın: mrename

Ayrıca komut dosyasında fotoğrafları ölçeklendirmek için isteğe bağlı bir açıklama özelliği de vardır (ImageMagick kullanarak).

Umarım bu bazı insanlar için yararlıdır.

#!/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";

0

-X/--keep-extensionSeçeneği rename(sürüm 1.600) ile kullanabilirsiniz :

-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 Homebrew'dan Mac ve Linuxbrew'dan Linux için kullanılabilir (elbette diğer yükleme seçeneklerinin yanı sıra).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.