ฉันต้องการเปลี่ยนชื่อไฟล์ในไดเรกทอรีเป็นตัวเลขตามลำดับ อ้างอิงจากวันที่สร้างไฟล์
ตัวอย่างเช่นsadf.jpg
การ0001.jpg
, wrjr3.jpg
การ0002.jpg
และอื่น ๆ จำนวนเลขศูนย์นำไปขึ้นอยู่กับจำนวนของไฟล์ (ความจำเป็นในการ zeroes พิเศษถ้าไม่จำเป็นต้องไม่ได้)
ฉันต้องการเปลี่ยนชื่อไฟล์ในไดเรกทอรีเป็นตัวเลขตามลำดับ อ้างอิงจากวันที่สร้างไฟล์
ตัวอย่างเช่นsadf.jpg
การ0001.jpg
, wrjr3.jpg
การ0002.jpg
และอื่น ๆ จำนวนเลขศูนย์นำไปขึ้นอยู่กับจำนวนของไฟล์ (ความจำเป็นในการ zeroes พิเศษถ้าไม่จำเป็นต้องไม่ได้)
คำตอบ:
ลองใช้การวนซ้ำlet
และprintf
สำหรับการขยาย:
a=1
for i in *.jpg; do
new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
mv -i -- "$i" "$new"
let a=a+1
done
การใช้-i
แฟล็กป้องกันการเขียนทับไฟล์ที่มีอยู่โดยอัตโนมัติ
printf -v new "%04d.jpg" ${a}
เพื่อใส่ค่าลงในตัวแปร และ((a++))
ทำงานเพื่อเพิ่มตัวแปร นอกจากนี้สิ่งนี้จะไม่ทำตามลำดับวันที่สร้างหรือย่อเล็กสุดซึ่งเป็นสิ่งที่ OP ระบุ อย่างไรก็ตามควรสังเกตว่า Linux / Unix ไม่ได้จัดเก็บวันที่สร้าง
mv -- "$i" "$new"
เพื่อจัดการชื่อไฟล์แหล่งที่มาที่เริ่มต้นด้วยเครื่องหมายขีดกลาง ตามที่เป็นอยู่mv
จะพยายามแยกชื่อไฟล์ดังกล่าวเป็นชุดธง
-i
ควรรวมอยู่ในคำตอบและควรเขียนใหม่ตามนั้น มันจะปลอดภัยมากขึ้น :(
ความงามในหนึ่งบรรทัด:
ls -v | cat -n | while read n f; do mv -n "$f" "$n.ext"; done
คุณสามารถเปลี่ยน.ext
ด้วย.png
, .jpg
ฯลฯ
ls | cat -n | while read n f; do mv "$f" `printf "%04d.extension" $n`; done
เพื่อให้มีจำนวนศูนย์เบาะ
-n
คำสั่ง mv เพื่อป้องกันการเขียนทับไฟล์โดยไม่ตั้งใจ ค้นพบวิธีนี้ยาก!
ls -1prt | grep -v "/$" | cat -n | while read n f; do mv -n "${f}" "$(printf "%04d" $n).${f#*.}"; done
ผลลัพธ์: (1) เรียงลำดับตามการปรับเปลี่ยนไฟล์ในภายหลังที่มีดัชนีภายหลัง (2) ไม่สนใจไดเรกทอรี - และไม่เรียกซ้ำ (3) ดัชนีแผ่น; (4) รักษานามสกุลเดิม
ฉันชอบโซลูชันของ gauteh สำหรับความเรียบง่าย แต่มีข้อเสียเปรียบที่สำคัญ เมื่อทำงานกับไฟล์หลายพันไฟล์คุณจะได้รับข้อความ "รายการอาร์กิวเมนต์ยาวเกินไป" ( มากกว่านี้ ) และที่สองสคริปต์จะช้าลงอย่างมาก ในกรณีของฉันใช้ไฟล์ประมาณ 36.000 สคริปต์ย้ายประมาณ หนึ่งรายการต่อวินาที! ฉันไม่ได้จริงๆว่าทำไมนี้เกิดขึ้น แต่กฎที่ผมได้จากเพื่อนร่วมงานเป็น"find
เป็นเพื่อนของคุณ"
find -name '*.jpg' | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command
ในการนับจำนวนไอเท็มและคำสั่ง build จะใช้gawk สังเกตความแตกต่างหลักแม้ว่า โดยค่าเริ่มต้นfind
ค้นหาไฟล์ในไดเรกทอรีปัจจุบันและไดเรกทอรีย่อยดังนั้นให้ จำกัด การค้นหาในไดเรกทอรีปัจจุบันเท่านั้นหากจำเป็น (ใช้man find
เพื่อดูว่า)
NR
สำหรับคำสั่งที่สั้นกว่า gawk '{ printf "mv %s %04d.jpg\n", $0, NR }'
$(rm -rf /).jpg
คิดว่าถ้าคุณมีไฟล์ชื่อ
for
วนซ้ำไม่ได้ใช้เวลา 1 วินาทีต่อไฟล์โดยพูดอย่างเคร่งครัด ใช้เวลานานในการเรียกชื่อไฟล์ 36,000 ชื่อจากระบบไฟล์จากนั้นวนซ้ำอย่างรวดเร็วพอสมควร ระบบไฟล์จำนวนมากมีปัญหากับไดเรกทอรีขนาดใหญ่โดยไม่คำนึงถึงคำสั่งที่คุณใช้อย่างแม่นยำ แต่โดยทั่วไปfind
จะเร็วกว่า shell wildcard เนื่องจากต้องดึงข้อมูลและเรียงลำดับรายการไฟล์ที่ตรงกัน
ด้วยคำสั่ง "เปลี่ยนชื่อ"
rename -N 0001 -X 's/.*/$N/' *.jpg
หรือ
rename -N 0001 's/.*/$N.jpg/' *.jpg
rename
(Linux Mint 13) ของฉันไม่มี-N
ตัวเลือก
rename
คำสั่ง แต่ฉันไม่เคยรู้เกี่ยวกับ-N
! ขอบคุณ!
rename
ลิงก์ที่โพสต์โดย @Bostrot นั้นเป็นเครื่องมือเปลี่ยนชื่ออีกอันหนึ่งและดูเหมือนว่า @RomanRhrnNesterov ใช้ลิงก์นั้น ¶สำหรับผู้ใช้ทั้งหมดrename
โดย Peder Stray และ Larry Wall (แพ็คเกจperl-rename
บน arch linux และแพ็คเกจrename
บน debian / ubuntu): คุณสามารถกำหนด$N
ตัวเอง:perl-rename '$N=sprintf("%04d",++$N); s/.*/$N.jpg/' *.jpg
การใช้โซลูชัน Pero บน OSX จำเป็นต้องแก้ไขบางอย่าง ฉันใช้:
find . -name '*.jpg' \
| awk 'BEGIN{ a=0 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' \
| bash
หมายเหตุ: แบ็กสแลชนั้นมีไว้เพื่อการต่อสาย
แก้ไข 20 กรกฎาคม 2558:
รวมคำติชมของ @ klaustopher เพื่ออ้างถึง\"%s\"
อาร์กิวเมนต์ของmv
คำสั่งเพื่อรองรับชื่อไฟล์ที่มีช่องว่าง
$(rm -rf /).jpg
คิดว่าถ้าคุณมีไฟล์ชื่อ
mv
แต่คุณควรพูดอาร์กิวเมนต์แรก หากคุณมีไฟล์ชื่อเช่นsome thing.jpg
สคริปต์ของคุณล้มเหลว นี่คือสิ่งที่ฉันใช้:find . -name '*.jpg' | awk 'BEGIN{ a=0 }{ printf "mv \"%s"\ wallpaper-%04d.jpg\n", $0, a++ }' | bash
-maxdepth 1
เพื่อทำงานเฉพาะใน jpgs ในไดเรกทอรีปัจจุบันเพราะจะปลอดภัยกว่าขออภัย
ls -1 *.jpg
แทนการค้นหามิฉะนั้นจะไม่ถูกจัดเรียง หรือเพิ่ม a |sort|
awk ก่อนหน้า
bash one ที่เรียบง่ายมากที่ใช้เก็บนามสกุลเดิมเพิ่มเลขศูนย์นำหน้าและใช้งานได้ใน OSX:
num=0; for i in *; do mv "$i" "$(printf '%04d' $num).${i#*.}"; ((num++)); done
รุ่นที่ง่ายกว่าของhttp://ubuntuforums.org/showthread.php?t=1355021
9.ext
มาก่อน11.ext
แต่เครื่องมืออื่น ๆ (เช่นls
) จะไม่ทำเช่นนั้น
ในการทำงานในทุกสถานการณ์ให้ใส่ \ "สำหรับไฟล์ที่มีช่องว่างในชื่อ
find . -name '*.jpg' | gawk 'BEGIN{ a=1 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' | bash
$(rm -rf /)
นั้นจึงยังคงได้รับเกียรติ
หากคุณrename
ไม่สนับสนุน-N
คุณสามารถทำสิ่งนี้:
ls -1 -c | xargs rename -n 's/.*/our $i; sprintf("%04d.jpg", $i++)/e'
แก้ไขหากต้องการเริ่มต้นด้วยหมายเลขที่กำหนดคุณสามารถใช้รหัส (ดูค่อนข้างน่าเกลียด) ด้านล่างเพียงแค่แทนที่ 123 ด้วยหมายเลขที่คุณต้องการ:
ls -1 -c | xargs rename -n 's/.*/our $i; if(!$i) { $i=123; } sprintf("%04d.jpg", $i++)/e'
สิ่งนี้แสดงรายการไฟล์ตามลำดับเวลาการสร้าง (ใหม่สุดก่อนเพิ่ม-r
ใน ls เพื่อย้อนกลับเรียงลำดับ) จากนั้นส่งรายการไฟล์นี้เพื่อเปลี่ยนชื่อ เปลี่ยนชื่อใช้รหัส perl ใน regex เพื่อจัดรูปแบบและตัวนับที่เพิ่มขึ้น
อย่างไรก็ตามหากคุณกำลังจัดการกับภาพ JPEG ที่มีข้อมูล EXIF ฉันขอแนะนำ exiftool
นี่คือจากเอกสาร exiftoolภายใต้ "ตัวอย่างการเปลี่ยนชื่อ"
exiftool '-FileName<CreateDate' -d %Y%m%d_%H%M%S%%-c.%%e dir
Rename all images in "dir" according to the "CreateDate" date and time, adding a copy number with leading '-' if the file already exists ("%-c"), and
preserving the original file extension (%e). Note the extra '%' necessary to escape the filename codes (%c and %e) in the date format string.
rename
อย่างไร
บน OSXให้ติดตั้งสคริปต์การเปลี่ยนชื่อจาก Homebrew:
brew install rename
จากนั้นคุณสามารถทำได้อย่างง่ายดายจริง ๆ ขัน:
rename -e 's/.*/$N.jpg/' *.jpg
หรือเพื่อเพิ่มคำนำหน้าดี:
rename -e 's/.*/photo-$N.jpg/' *.jpg
Global symbol "$N" requires explicit package name (did you forget to declare "my $N"?) at (user-supplied code).
ทำตามคำสั่งเปลี่ยนชื่อไฟล์ทั้งหมดเป็นลำดับและยังเป็นนามสกุลเล็ก:
rename --counter-format 000001 --lower-case --keep-extension --expr='$_ = "$N" if @EXT' *
ฉันมีปัญหาที่คล้ายกันและเขียนเชลล์สคริปต์ด้วยเหตุผลนั้น ฉันตัดสินใจที่จะโพสต์โดยไม่คำนึงถึงคำตอบที่ดีมากมายที่โพสต์แล้วเพราะฉันคิดว่ามันจะมีประโยชน์สำหรับใครบางคน อย่าลังเลที่จะปรับปรุงมัน!
@Gnutt พฤติกรรมที่คุณต้องการสามารถทำได้โดยการพิมพ์ดังต่อไปนี้:
./numerate.sh -d <path to directory> -o modtime -L 4 -b <startnumber> -r
หากตัวเลือก-r
นั้นถูกปล่อยออกมาการทำซ้ำจะถูกจำลองเท่านั้น (น่าจะเป็นประโยชน์สำหรับการทดสอบ)
otion L อธิบายความยาวของจำนวนเป้าหมาย (ซึ่งจะเต็มไปด้วยเลขศูนย์นำ) ก็ยังเป็นไปได้ที่จะเพิ่มคำนำหน้า / -p <prefix>
-s <suffix>
ต่อท้ายด้วยตัวเลือก
ในกรณีที่มีคนต้องการจัดเรียงไฟล์เป็นตัวเลขก่อนที่พวกเขาจะได้รับหมายเลขเพียงลบ-o modtime
ตัวเลือก
a=1
for i in *.jpg; do
mv -- "$i" "$a.jpg"
a=`expr $a + 1`
done
ให้เราสมมติว่าเรามีไฟล์เหล่านี้ในไดเรกทอรีโดยเรียงตามลำดับการสร้างรายการแรกสุด:
a.jpg
b.JPG
c.jpeg
d.tar.gz
e
จากนั้นls -1cr
ส่งออกรายการด้านบนทั้งหมด จากนั้นคุณสามารถใช้rename
:
ls -1cr | xargs rename -n 's/^[^\.]*(\..*)?$/our $i; sprintf("%03d$1", $i++)/e'
ซึ่งผลลัพธ์
rename(a.jpg, 000.jpg)
rename(b.JPG, 001.JPG)
rename(c.jpeg, 002.jpeg)
rename(d.tar.gz, 003.tar.gz)
Use of uninitialized value $1 in concatenation (.) or string at (eval 4) line 1.
rename(e, 004)
คำเตือน” การใช้ค่าเริ่มต้น […]” จะปรากฏขึ้นสำหรับไฟล์ที่ไม่มีนามสกุล; คุณสามารถละเว้นได้
ลบออก-n
จากrename
คำสั่งเพื่อใช้การเปลี่ยนชื่อจริง
คำตอบนี้เป็นแรงบันดาลใจจากคำตอบของลุคของเมษายน 2014 มันจะเพิกเฉยต่อข้อกำหนดของ Gnutt ในการกำหนดจำนวนของเลขศูนย์นำขึ้นอยู่กับจำนวนไฟล์ทั้งหมด
ls -1tU
เวลาสร้าง มันจำเป็นต้องrename
ติดตั้งซึ่งฉันไม่ได้มี
อีกครั้งโดยใช้วิธีการของ Pero ด้วยการปรับเปลี่ยนเพียงเล็กน้อยเพราะfind
จะข้ามทรีไดเรกทอรีในรายการสั่งซื้อจะถูกเก็บไว้ในรายการไดเรกทอรี นี้จะ (ส่วนใหญ่) จะสอดคล้องกันจากการเรียกใช้เพื่อทำงานบนเครื่องเดียวกันและเป็นหลักจะเป็น "ลำดับการสร้างไฟล์ / ไดเรกทอรี" ถ้าไม่มีการลบ
อย่างไรก็ตามในบางกรณีคุณจำเป็นต้องได้รับการสั่งซื้อทางตรรกะพูดตามชื่อซึ่งใช้ในตัวอย่างนี้
find -name '*.jpg' | sort -n | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command
blahblah; rm -r * blahblah.jpg
?
จัดเรียงตามเวลา จำกัด เฉพาะ jpg นำเลขศูนย์และชื่อฐาน (ในกรณีที่คุณต้องการ)
ls -t *.jpg | cat -n | \
while read n f; do mv "$f" "$(printf thumb_%04d.jpg $n)"; done
(ทั้งหมดในบรรทัดเดียวไม่มี\
)
ls
ในสคริปต์
ls -1tr | rename -vn 's/.*/our $i;if(!$i){$i=1;} sprintf("%04d.jpg", $i++)/e'
เปลี่ยนชื่อ -vn - ลบnสำหรับโหมดทดสอบปิด
{$ i = 1;} - ควบคุมหมายเลขเริ่มต้น
"% 04d.jpg" - การควบคุมนับศูนย์04และตั้งค่าส่วนขยายเอาท์พุท. jpg
rename -v -n 's/../our $i;if(!$i){$i=1;} sprintf("%02d", $i++)/e' *
สำหรับฉันการรวมกันของคำตอบนี้ทำงานได้อย่างสมบูรณ์แบบ:
ls -v | gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | bash
ls -v
ช่วยในการสั่งซื้อ 1 10 9 ในการแก้ไข: 1 9 10 เพื่อหลีกเลี่ยงปัญหาส่วนขยายชื่อไฟล์ด้วย jpg JPG jpeggawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }'
สร้างใหม่ด้วยอักขระ 4 ตัวและเลขศูนย์นำหน้า โดยการหลีกเลี่ยง mv ฉันจะไม่พยายามเขียนทับสิ่งที่มีอยู่แล้วโดยบังเอิญโดยมีหมายเลขเดียวกันโดยไม่ตั้งใจbash
รันระวังสิ่งที่ @xhienne พูดการวางเนื้อหาที่ไม่รู้จักเพื่อทุบตีมีความเสี่ยงด้านความปลอดภัย แต่นี่ไม่ใช่กรณีสำหรับฉันเนื่องจากฉันใช้รูปภาพที่สแกน
คุณยังสามารถใช้ls
ls *.JPG| awk 'BEGIN{ a=0 }{ printf "mv %s gopro_%04d.jpg\n", $0, a++ }' | bash
blahblah; rm -r * blahblah.JPG
?
โซลูชันอื่น ๆ ส่วนใหญ่จะเขียนทับไฟล์ที่มีอยู่แล้วซึ่งตั้งชื่อเป็นหมายเลขแล้ว นี่เป็นปัญหาโดยเฉพาะอย่างยิ่งหากเรียกใช้สคริปต์เพิ่มไฟล์มากขึ้นแล้วเรียกใช้สคริปต์อีกครั้ง
สคริปต์นี้จะเปลี่ยนชื่อไฟล์ตัวเลขที่มีอยู่ก่อน:
#!/usr/bin/perl
use strict;
use warnings;
use File::Temp qw/tempfile/;
my $dir = $ARGV[0]
or die "Please specify directory as first argument";
opendir(my $dh, $dir) or die "can't opendir $dir: $!";
# First rename any files that are already numeric
while (my @files = grep { /^[0-9]+(\..*)?$/ } readdir($dh))
{
for my $old (@files) {
my $ext = $old =~ /(\.[^.]+)$/ ? $1 : '';
my ($fh, $new) = tempfile(DIR => $dir, SUFFIX => $ext);
close $fh;
rename "$dir/$old", $new;
}
}
rewinddir $dh;
my $i;
while (my $file = readdir($dh))
{
next if $file =~ /\A\.\.?\z/;
my $ext = $file =~ /(\.[^.]+)$/ ? $1 : '';
rename "$dir/$file", sprintf("%s/%04d%s", $dir, ++$i, $ext);
}
oneliner นี้แสดงรายการไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันเรียงลำดับตามการสร้างเวลาในลำดับย้อนกลับ (หมายถึงไฟล์ที่เก่าที่สุดอยู่ที่จุดเริ่มต้น) และเปลี่ยนชื่อโดยอัตโนมัติด้วยศูนย์ต่อท้ายตามจำนวนไฟล์ที่ต้องการ นามสกุลไฟล์จะถูกเก็บไว้
ฉันมักจะมีเพียงโฟลเดอร์เดียวตั้งแต่ปีสำหรับรูปภาพโทรศัพท์มือถือและภาพยนตร์ เมื่อใช้คำสั่งนี้รูปภาพและภาพยนตร์ของฉันก็พร้อมสำหรับการนำเสนอภาพนิ่งในลำดับที่ถูกต้องบนทีวีหรือเก็บถาวรเช่นกัน
ระวังว่าถ้าคุณมีการชนกันของชื่อไฟล์คุณกำลังสูญเสียไฟล์ ดังนั้นก่อนเปลี่ยนชื่อเป็นสิ่งที่แปลกชอบtemp001.jpg
แล้วดำเนินการเป็นชื่อไฟล์สุดท้ายของคุณ
DIGITS=$(ls | wc -l | xargs | wc -c | xargs); ls -tcr | cat -n | while read n f; do mv "$f" "$(printf "%0${DIGITS}d" $n).${f##*.}"; done
ls
ไม่ใช่ครั้งเดียว แต่ดูเหมือนว่าสองครั้งจะดีกว่า แต่ฉันไม่ได้ศึกษาในเชิงลึก
ls
ดังนั้นจึงจำเป็นต้องมีสองข้อ 3. คำสั่งดังกล่าวเป็นหนึ่งนัดและไม่ได้รวมอยู่ในสคริปต์ดังนั้นจึงมีเหตุผลว่าทำไมผู้คนถึงนิยมใช้งานแบบตอร์ปิโดหนึ่งเดียว
นี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน
ฉันได้ใช้คำสั่งเปลี่ยนชื่อเพื่อที่ว่าถ้าไฟล์ใดมีช่องว่างในชื่อของมันแล้วคำสั่งmvไม่สับสนระหว่างช่องว่างและไฟล์จริง
ที่นี่ฉันแทนที่ช่องว่าง '' ในชื่อไฟล์ด้วย '_' สำหรับไฟล์ jpg ทั้งหมด
#! / bin / ทุบตี เปลี่ยนชื่อ 'y / / _ /' * jpg #replacing เว้นวรรคด้วย _ ให้ x = 0; สำหรับฉันใน * .jpg; ทำ ให้ x = (x + 1) mv $ i $ x.jpg เสร็จแล้ว
ทุกวันนี้มีตัวเลือกหลังจากคุณเลือกหลายไฟล์เพื่อเปลี่ยนชื่อ (ฉันเห็นในตัวจัดการไฟล์ thunar)
พรอมต์มาพร้อมกับไฟล์ทั้งหมดใน dir นั้นโดยเฉพาะเพียงตรวจสอบกับส่วนหมวดหมู่
สคริปต์นี้จะเรียงลำดับไฟล์ตามวันที่สร้างบนทุบตี Mac OS ฉันใช้เพื่อเปลี่ยนชื่อวิดีโอเป็นจำนวนมาก เพียงเปลี่ยนนามสกุลและส่วนแรกของชื่อ
ls -trU *.mp4| awk 'BEGIN{ a=0 }{ printf "mv %s lecture_%03d.mp4\n", $0, a++ }' | bash
blahblah; rm -r * blahblah.mp4
?
นี่คือวิธีแก้ไขปัญหาอื่นด้วยคำสั่ง "เปลี่ยนชื่อ":
find -name 'access.log.*.gz' | sort -Vr | rename 's/(\d+)/$1+1/ge'
rename 's/(\d+)/sprintf("%04d",$1)+1/ge'
คำตอบของ Pero ทำให้ฉันมาที่นี่ :)
ฉันต้องการเปลี่ยนชื่อไฟล์เมื่อเทียบกับเวลาเนื่องจากผู้ดูภาพไม่ได้แสดงรูปภาพตามลำดับเวลา
ls -tr *.jpg | # list jpegs relative to time
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command
blahblah; rm -r * blahblah.jpg
? เป็นเพียงตัวอย่างที่รุนแรง
หากคุณกำลังใช้ Annotator สำหรับการติดฉลากภาพ
$ make qt5py3
$ python3 labelImg.py
ในการเปลี่ยนหมายเลข 6000 ไฟล์ในโฟลเดอร์เดียวคุณสามารถใช้ตัวเลือก 'เปลี่ยนชื่อ' ของโปรแกรม ACDsee
สำหรับการกำหนดคำนำหน้าให้ใช้รูปแบบนี้: ####"*"
จากนั้นตั้งค่าหมายเลขเริ่มต้นแล้วกดเปลี่ยนชื่อจากนั้นโปรแกรมจะเปลี่ยนชื่อไฟล์ทั้งหมด 6,000 ไฟล์ด้วยหมายเลขเรียงลำดับ