การเปลี่ยนชื่อกลุ่มไฟล์ด้วยการประทับเวลาที่แก้ไขวันที่ท้ายชื่อไฟล์หรือไม่


14

ดังนั้นฉันจะมีไดเรกทอรีที่มีไฟล์มากมายเช่น g.txt ซึ่ง g.txt ได้รับการแก้ไขครั้งล่าสุดเมื่อวันที่ 20 มิถุนายน 2012

ฉันจะเปลี่ยนชื่อแบทช์ไฟล์ทั้งหมด (เช่น g.txt) ด้วยวันที่แก้ไขล่าสุดของวันที่ 20 มิถุนายน 2012 ต่อท้ายได้อย่างไร

คำตอบ:


13

Bash หนึ่งซับอย่างรวดเร็วและสกปรกเพื่อเปลี่ยนชื่อไฟล์ทั้งหมด (แบบกลม) ในไดเรกทอรีปัจจุบันจากfilename.txtเป็นfilename.txt-20120620:

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

Bash nerd ที่กล้าได้กล้าเสียจะพบว่ามีขอบตัวเรือนบางอย่างที่จะทำลายมันฉันแน่ใจ :)

เห็นได้ชัดว่าสิ่งนี้ไม่ได้ทำสิ่งที่ต้องการเช่นการตรวจสอบว่าไฟล์มีบางสิ่งที่ดูเหมือนวันที่สิ้นสุดอยู่แล้ว


2
+1 ดูดี คุณสามารถทำให้แข็งแกร่งขึ้นเล็กน้อยโดยใช้ '-' เป็นอาร์กิวเมนต์แรกกับ mv ผู้พิทักษ์ฉากต่อสู้กับ filenaes เริ่มต้นด้วย '-'
cas

5
dateการใช้งานประเภทใดนั้น GNU ของฉันdateดูเหมือนจะไม่จัดการกับอินพุต
จัดการ

coreutils 8.4 บน RHEL 6
jgoldschrafe

2
@jgoldschrafe คุณแน่ใจหรือว่ารหัสนั้นเหมาะสมกับคุณ? pastebin.com/nNYubf3A
จัดการ

5
การจัดการที่ดีจับ GNU ของฉันวันที่ 8.13 ไม่รองรับการอ่านจาก stdin เช่นกัน มันรองรับการใช้เวลา mod ของไฟล์ที่มี "-r" - เช่น "วันที่ +% Y% m% d% -r $ f" ดังนั้นสถิติจึงไม่จำเป็นแม้แต่ในกรณีนี้
cas

18

นี่คือเวอร์ชั่นหนึ่งของสายการบินเดียวของ goldschrafe ที่:

  • ไม่ใช้สถิติ
  • ทำงานร่วมกับวันที่ GNU รุ่นก่อนหน้า
  • copes อย่างถูกต้องกับช่องว่างใด ๆ ในชื่อไฟล์
  • เช่นเดียวกันกับชื่อไฟล์ที่ขึ้นต้นด้วยเส้นประ

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done


1
คุณควรสร้างมันมิdate -r "$f" +%Y%m%dฉะนั้นมันจะไม่ทำงานหากPOSIXLY_CORRECTอยู่ในสภาพแวดล้อม โดยทั่วไปตัวเลือกควรดำเนินการก่อนอาร์กิวเมนต์อื่น ๆ
Stéphane Chazelas

นี่ควรเป็น "คำตอบที่ถูกต้อง"
invalidusername

"${f}"แน่นอนคุณไม่จำเป็นต้องจัดฟันใน
G-Man กล่าวว่า 'Reinstate Monica'

แต่คุณจะทำให้มันเป็นเช่นนั้นได้อย่างไรเมื่อวันที่เราเตรียมไว้เช่น "Ymd-filename"
timebandit

2

zsh แบบบังคับด้านหนึ่ง (ไม่นับการโหลดครั้งเดียวของส่วนประกอบเสริม):

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

เราใช้statbuiltin จากzsh/statโมดูลและzmvฟังก์ชั่นเพื่อเปลี่ยนชื่อไฟล์ และนี่คือส่วนเพิ่มเติมที่ระบุวันที่ก่อนส่วนขยายหากมี

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'

1

ตามที่ฉันเข้าใจเราไม่ทราบล่วงหน้าว่าวันที่แก้ไขคืออะไร ดังนั้นเราจำเป็นต้องได้รับจากแต่ละไฟล์จัดรูปแบบผลลัพธ์และเปลี่ยนชื่อไฟล์แต่ละวิธีเพื่อให้มีวันที่แก้ไขในชื่อไฟล์

คุณสามารถบันทึกสคริปต์นี้เป็นแบบ "modif_date.sh" และทำให้สามารถเรียกใช้งานได้ เราเรียกใช้ไดเรกทอรีเป้าหมายเป็นอาร์กิวเมนต์:

modif_date.sh txt_collection

โดยที่ "txt_collection" เป็นชื่อของไดเรกทอรีที่เรามีไฟล์ทั้งหมดที่เราต้องการเปลี่ยนชื่อ

#!/bin/sh

# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
    echo "Usage: $0 directory"
    exit 1
fi

# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
  /*) work_dir=${1};;
  *) work_dir=${PWD}/${1};;
esac

# We need a for loop to treat file by file inside our target directory
for i in *; do
    # If the modification date is in the same year, "ls -l" shows us the timestamp.
    # So in this case we use our current year. 
    test_year=`ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }'`
    case ${test_year} in *:*) 
        modif_year=`date '+%Y'`
        ;;
    *)
        modif_year=${test_year}
        ;;
    esac
    # The month output from "ls -l" is in short names. We convert it to numbers.
    name_month=`ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }'`
    case ${name_month} in
            Jan) num_month=01 ;;
            Feb) num_month=02 ;;
        Mar) num_month=03 ;;
        Apr) num_month=04 ;;
        May) num_month=05 ;;
        Jun) num_month=06 ;;
        Jul) num_month=07 ;;
        Aug) num_month=08 ;;
        Sep) num_month=09 ;;
        Oct) num_month=10 ;;
        Nov) num_month=11 ;;
        Dec) num_month=12 ;;
        *) echo "ERROR!"; exit 1 ;;
    esac
    # Here is the date we will use for each file
    modif_date=`ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }'`${num_month}${modif_year}
    # And finally, here we actually rename each file to include
    # the last modification date as part of the filename.
    mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done

1
อ่าน man page สำหรับ stat (1) เพื่อค้นหาว่าคุณจะย่อขนาดสคริปต์ของคุณได้ประมาณ 3/4 ... สิ่งที่กล่าวมาส่วนใหญ่เป็นการประดิษฐ์วงล้อใหม่ โดยเฉพาะอย่างยิ่ง 'stat -c% Y' จะให้เวลาการแก้ไขไฟล์แก่คุณในไม่กี่วินาทีนับตั้งแต่ยุค (1970-01-01 00:00:00) จากนั้นสามารถใช้เป็นอินพุตถึงวันที่ (1) เพื่อจัดรูปแบบการประทับเวลาตามที่ต้องการ ดูคำตอบของ jgoldschrafe ด้านบนสำหรับตัวอย่าง
cas

@CraigSanders ข้อเสียคือสคริปต์นี้ทำงานภายใต้ระบบปฏิบัติการอื่นที่ไม่ใช่ Linux ซึ่งมีstatยูทิลิตี้อื่นหรือไม่มีเลย
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

โปรดทราบว่าการแยกการส่งออกของlsไม่น่าเชื่อถือ ในตัวแปร unix บางชื่อผู้ใช้และกลุ่มสามารถมีช่องว่างซึ่งจะทำให้การจัดตำแหน่งคอลัมน์วันที่
Gilles 'หยุดความชั่วร้าย'

@giles: จริง แต่ทุกคนที่เหมาะสม :-) จะติดตั้ง GNU coreutils (และเครื่องมือ GNU อื่น ๆ ทั้งหมด) บนระบบที่ไม่ใช่ Linux มันเป็นวิธีที่ง่ายที่สุดที่จะได้รับไม่เพียง แต่ชุดเครื่องมือ userland ที่ดี แต่ยังเป็นชุดที่สอดคล้องกันโดยไม่คำนึงถึงเคอร์เนลพื้นฐาน
cas

1
(ต่อ) ... (5) ข้อผิดพลาดอื่น: ถือว่าวันที่ / เวลาใด ๆ ที่แสดงโดยls เป็นวันที่และเวลา (แทนที่จะเป็นวันที่และปี) จะต้องอยู่ในปีปัจจุบัน นี่ไม่เป็นความจริง. ในช่วงหกเดือนที่ผ่านมา ที่อาจเป็นในปีก่อนหน้า (เช่น 27 ก.ย. 2559 ถึง 31 ธ.ค. 2559 อยู่ในช่วงหกเดือนที่ผ่านมา) (6) ด้วยความเสี่ยงที่จะเกิดเรื่องไร้สาระกับวิกิพีเดียของ Greg (ซึ่ง @Gilles ได้อ้างถึงแล้ว) ชื่อไฟล์ที่มีบรรทัดใหม่และช่องว่างอาจทำให้สิ่งนี้ล้มเหลว … (ต่อ)
G-Man พูดว่า 'Reinstate Monica'

0

นี่คือเวอร์ชั่นของหนึ่งซับของคาสิโน (ขึ้นอยู่กับ goldschrafe ของ oneliner) ขยายด้วยidempotence ,

คือขยายไปยังไฟล์คำนำหน้าด้วยเวลาวันที่และการทำเช่นนี้เฉพาะสำหรับผู้ที่ยังไม่มีคำนำหน้าเวลาวันที่แต่สำหรับผู้ที่ไม่ได้มีคำนำหน้าวันเวลาเลย

ใช้ตัวพิมพ์: มีประโยชน์หากคุณเพิ่มไฟล์ใหม่ลงในไดเรกทอรีและต้องการเพิ่มคำนำหน้าเวลาวันที่ให้กับไฟล์ที่ยังไม่มี

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done

หากการประทับเวลาไฟล์ของคุณถูกเมาและเป็น jpegs คุณอาจต้องการแก้ไขเพื่อแก้ไขด้วยข้อมูล EXIF: for f in *.jpg ; do jhead -ft "$f" ; doneแหล่งที่มา: unix.stackexchange.com/a/290755/9689
Grzegorz Wierzowiecki
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.