คัดลอกกลุ่มของไฟล์ (Filename *) ไปยังการสำรองข้อมูล (Filename * .bak)


13

พื้นหลัง

ใน Linux คุณสามารถ:

  • แสดงรายการกลุ่มไฟล์ด้วย ls Filename*
  • ลบกลุ่มของไฟล์ด้วย rm Filename*
  • ย้ายกลุ่มของไฟล์ด้วย mv Filename* /New/Directory
  • แต่คุณไม่สามารถคัดลอกกลุ่มของไฟล์ด้วย:cp Filename* *.bak

เปลี่ยนcpคำสั่งLinux เพื่อคัดลอกกลุ่มของไฟล์

ฉันมีกลุ่มไฟล์ที่ฉันต้องการคัดลอกโดยไม่ต้องป้อนชื่อทีละตัวและใช้cpคำสั่ง:

$ ls gmail-meta3*
gmail-meta3                          gmail-meta3-REC-1558392194-26467821
gmail-meta3-LAB-1558392194-26467821  gmail-meta3-YAD-1558392194-26467821

ฉันจะใช้คำสั่ง DOS แบบเก่าได้copy gmail-meta3* *.bakอย่างไร

ฉันไม่ต้องการพิมพ์คำสั่งที่คล้ายกันสี่ครั้ง:

cp gmail-meta3-LAB-1558392194-26467821 gmail-meta3-LAB-1558392194-26467821.bak

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

copy gmail-meta3* *.bak

หรือพวกเขาอาจพิมพ์:

copy gmail-meta3* save-*

1
ปัญหาพบกับฉันโดยใช้โอเปอเรเตอร์ glob สองครั้งซึ่งไม่มีคำสั่งอื่นที่คุณใช้ ทุบตีไม่ฉลาดพอที่จะจัดการมัน
qwr

2
@qwr ความจริงที่ว่า bash ขยาย metacharacters และโทเค็นอินพุตก่อนส่งไปยังคำสั่งที่จะเรียกใช้งานเป็นส่วนหนึ่งของการออกแบบของ UNIX shells เพื่อลองและตั้งโปรแกรมข้อยกเว้นสำหรับคำสั่ง cp จะทำลายความสอดคล้องทั้งหมดของ bash ซึ่งจะไม่ฉลาดเลย เป็นแบบฝึกหัดลองคิดดูว่าเกิดอะไรขึ้นที่นี่และทำไมมันถึงเป็นตัวขยายลักษณะของเชลล์ที่ทำให้มันเป็นเช่นนั้น:touch aa ab ba; mkdir bb; cp a* b*; ls *
Mike S

@ MikeS ขอบคุณสำหรับคำแนะนำ เมื่อวานมีคนอื่นพูดว่าคุณสามารถใช้ไวด์การ์ด*สำหรับชื่อไฟล์ต้นทาง แต่ไม่ใช่สำหรับชื่อไฟล์เป้าหมาย เช่นแทนที่ตัวแทน (ฉันคิดว่า##ถูกแนะนำ แต่ฉันเอนตัวไป%) จะต้องใช้สำหรับเป้าหมาย ฉันคิดว่านี่คือสิ่งที่คุณกำลังเสริม? ฉันไม่ได้คาดหวังว่าจะเปลี่ยนcpคำสั่งเลย เพียงสร้างสคริปต์ตัวตัดที่เรียกcopyว่า emulated (ภายในเหตุผล) คำสั่ง DOS copy
WinEunuuchs2Unix

@ WinEunuuchs2Unix บุคคลนั้นถูกต้อง เชลล์เมตาอักขระที่เป็นอิสระจากคำสั่ง ดังนั้นสัญลักษณ์ทั้งหมดจะพยายามและจับคู่ไฟล์ทั้งหมดที่ตรงกับรูปแบบ หากคุณกำลังพยายามทำให้วัตถุประสงค์ทั่วไป "จับคู่ทุกอย่างและคัดลอกไปยังสิ่งที่พวกเขาเป็น แต่เพิ่มโปรแกรมต่อท้ายนี้" จากนั้นใช่ให้ใส่เมตาอักขระที่ไม่ใช้การหลีกเลี่ยงเป้าหมายอาจจะไม่ทำในสิ่งที่คุณต้องการ เพราะเมตาอักขระทั้งหมดในบรรทัดคำสั่งเชลล์จะถูกขยาย หากคุณรู้แน่ชัดว่าตัวชี้เป้าหมายจะไม่ทำการจับคู่คุณสามารถใช้มันได้เนื่องจากเชลล์ไม่สามารถขยายได้
Mike S

... แต่นั่นจะเป็นสิ่งที่น่าเกลียดที่ต้องทำ ดีกว่าที่จะใช้ตัวละครพิเศษ % หรือขีดล่างดี แต่โดยทั่วไปแล้วไม่ใช่ metacharacters (แต่ควรระวังการใช้% ในไฟล์ crontab เป็นพิเศษ)
Mike S

คำตอบ:


14

นี่คือตัวอย่างของการใช้งานผิดปรกติหนึ่งครั้งsedซึ่งสามารถใช้ได้กับงานนี้:

sed -i.bak '' file-prefix*

ด้วยวิธีนี้จริง ๆ แล้วsedจะไม่เปลี่ยนไฟล์เพราะเราไม่ได้ให้คำสั่งใด ๆ''แต่เนื่องจากตัวเลือก-i[suffix]มันจะสร้างสำเนาสำรองของแต่ละไฟล์ ฉันพบวิธีนี้เมื่อฉันกำลังค้นหา มีวิธีการสร้างสำเนาสำรองของไฟล์โดยไม่ต้องพิมพ์ชื่อสองครั้งหรือไม่


FYI: $ time sed -i.bak '' gmail-meta3*=real 0m0.069s
WinEunuuchs2Unix

หากไฟล์มีอยู่แล้ว: real 0m0.037s. หากไฟล์ที่ถูกลบและใช้เวลาใกล้ที่สองเพื่อความเร็ว:cp real 0m0.051s
WinEunuuchs2Unix

@xiota จุดที่น่าสนใจ ปรากฎว่าsedเร็วขึ้นเมื่อมีไฟล์เป้าหมายอยู่แล้ว แต่cpจะช้ากว่าเมื่อมีไฟล์เป้าหมายอยู่ จริง ๆ แล้วฉันล้างแคชและบัฟเฟอร์มากกว่าsyncเมื่อทำการทดสอบเวลาขนาดใหญ่ แต่ฉันไม่ได้ในเวลานี้ เนื่องจากสิ่งนี้สามารถพูดนอกเรื่องเป็นสบู่นอกหัวข้อคำถามที่แตกต่างกันทั้งหมดฉันเสียใจที่แบ่งปันผลการทดสอบของฉัน :( มันสายเกินไปที่จะแกล้งบทสนทนานี้ไม่เคยเกิดขึ้นหรือไม่ขนาดของเมตาดาต้าข้อความ FYI gmail คือ 2.5 MB และ 3 ดัชนีไฟล์ประมาณ 800 KB นอกจากนี้ยังไม่ใช่ฮาร์ดดิสก์มันเป็น Samsung Pro 960 NVMe SSD ใน 4 ช่องทาง
WinEunuuchs2Unix

1
อาจไม่สำคัญว่าคุณมีอุปกรณ์เก็บข้อมูลใดสำหรับการทดสอบเหล่านี้หากเกิดขึ้นในเครื่อง Linux เคอร์เนลดีมากในการบัฟเฟอร์ไฟล์ในหน่วยความจำ นั่นคือสิ่งที่ค่า "บัฟ / แคช" คือเมื่อใช้freeคำสั่ง การเขียนที่แท้จริงไปยังอุปกรณ์เกิดขึ้นในขณะนั้นซึ่งถูกเลือกโดยอัลกอริทึมที่คำนึงถึงอายุของแคชและแรงกดดันของหน่วยความจำบนเครื่อง หากคุณลองการทดสอบหลายครั้งไฟล์แรกที่อ่านจะหลุดออกจากดิสก์ แต่การอ่านครั้งถัดไปอาจเป็นไปได้ว่าหน่วยความจำไม่ตรง (ดูsync; echo 3 > /proc/sys/vm/drop_caches)
Mike S

เมื่อวานนี้ผมทำไม่กี่ทดสอบกับไฟล์ขนาดใหญ่กว่า 2GB และ - ใช่วิธีนี้ค่อนข้างช้ากว่าการใช้ของcpคำสั่ง แต่ฉันไม่สามารถบอกว่ามีความแตกต่างอย่างมีนัยสำคัญประสิทธิภาพ
pa4080

13

คุณสามารถใช้find:

find . -max-depth 1 -name 'gmail-meta3*' -exec cp "{}" "{}.bak" \;

ที่จะพบในไดเรกทอรีปัจจุบัน.ทุกไฟล์ที่มีชื่อตรงกับรูปแบบ glob (โปรดคำนึงถึงเครื่องหมายคำพูดเดี่ยวรอบ ๆ รูปแบบเพื่อป้องกันไม่ให้เชลล์กลม) สำหรับแต่ละไฟล์ที่พบมันจะดำเนินการcpจากชื่อถึง name.bak The \; ในตอนท้ายทำให้แน่ใจว่ามันจะทำทีละไฟล์แทนที่จะส่งทั้งหมดในครั้งเดียว ความลึกสูงสุดเท่ากับ 1 ค้นหาไดเรกทอรี cuurent แทนการเรียกซ้ำ


1
มันจะทำงานกับfind . -max-depth 1 -name '"$1"'' -exec cp "{}" "{}$2" \;เมื่อ $ 1 เป็นแหล่งข้อมูลและ $ 2 คือส่วนขยาย
WinEunuuchs2Unix

$ 2 ควรใช้แทนได้ตราบใดที่มันสมเหตุสมผล $ 1 อาจมีความซับซ้อนมากขึ้นเนื่องจากเราไม่สามารถทำการทดแทนตัวแปรภายในเครื่องหมายคำพูดเดี่ยวได้ ฉันไม่แน่ใจทันที แต่อาจเป็นไปได้ที่จะใช้ $ 1 ในเครื่องหมายคำพูดคู่เนื่องจากรูปแบบจะถูกเก็บไว้ในสตริง
cbojar

11

คุณสามารถใช้วงด้วยfor bashโดยปกติฉันจะพิมพ์มันเป็นซับเดี่ยวเพราะนี่ไม่ใช่งานที่ฉันต้องทำบ่อย ๆ :

for f in test* ; do cp -a "$f" "prefix-${f}.ext" ; done

อย่างไรก็ตามหากคุณต้องการใช้เป็นสคริปต์:

cps() {
   [ $# -lt 2 ] && echo "Usage: cps REGEXP FILES..." && return 1

   PATTERN="$1" ; shift

   for file in "$@" ; do
      file_dirname=`dirname "$file"`
      file_name=`basename "$file"`
      file_newname=`echo "$file_name" | sed "$PATTERN"`

      if [[ -f "$file" ]] && [[ ! -e "${file_dirname}/${file_newname}" ]] ; then
         cp -a "$file" "${file_dirname}/${file_newname}"
      else
         echo "Error: $file -> ${file_dirname}/${file_newname}"
      fi
   done
}

renameการใช้งานคล้ายกับ ทดสอบ:

pushd /tmp
mkdir tmp2
touch tmp2/test{001..100}     # create test files
ls tmp2
cps 's@^@prefix-@ ; s@$@.bak@' tmp2/test*    # create backups
cps 's@$@.bak@' tmp2/test*    # more backups ... will display errors
ls tmp2
\rm -r tmp2                   # cleanup
popd

FYI: $ time for f in gmail-meta3* ; do cp -a "$f" "${f}.bak" ; done=real 0m0.046s
WinEunuuchs2Unix

อืมฉันไม่ต้องการปรับให้เหมาะสมสำหรับเวลา เป็น0.046วินาทีซึ่งหมายถึง 0 วินาทีสำหรับการรับรู้ของมนุษย์ ฉันแค่พยายามแสดงให้เห็นว่าฉันกำลังทดสอบโพสต์คำตอบและส่งผ่านเกร็ดความรู้ที่น่าสนใจให้กับผู้ชมที่ดูsedคำสั่งด้านบน หรืออย่างน้อยฉันก็สนใจที่sedจะเปรียบเทียบกับcp....
WinEunuuchs2Unix

วิธีการแก้ปัญหาของคุณกับcpจะเร็วกว่าวิธีการแก้ปัญหาที่มีsedแต่ ดังนั้นจึงเป็นสาเหตุของการเฉลิมฉลอง :)
WinEunuuchs2Unix

(1)  -aเป็นผู้ดำเนินการทดสอบที่ไม่ได้มาตรฐาน ทำไมไม่ใช้-e? (2)“ ไม่สามารถสร้างไดเรกทอรีชั่วคราว” เป็นข้อความแสดงข้อผิดพลาดที่ทำให้เข้าใจผิด (3) เหตุใดจึงไม่ใช้เพียงmktemp -d? (4) คุณควรทดสอบสถานะทางออก ตัวอย่างเช่นคุณควรจะพูดหรือ! mkdir "$FOLDER" && echo "Unable to create temporary directory." && return 1mkdir "$FOLDER" || { echo "Unable to create temporary directory."; return 1;}เช่นเดียวกันสำหรับcpและ  rename(และอาจจะยิ่งpushdถ้าคุณต้องการระวัง) … (ต่อ)
G-Man พูดว่า 'Reinstate Monica'

(ต่อ) … (5) Arrggghhhh! อย่าพูด$@; "$@"พูด (5b)  ไม่มีความจำเป็นที่จะใช้เป็น{และ }เมื่อคุณอ้างอิงตัวแปรในแบบที่คุณกำลังทำ ( "${FOLDER}",  "${PATTERN}" และ  "${file}"); เพียงแค่ทำ"$FOLDER",  และ"$PATTERN""$file"(6) นี่ถือว่าไฟล์อยู่ในไดเรกทอรีปัจจุบัน  cps 's/$/.bak/' d/fooจะคัดลอกd/fooไปfoo.bak ในไดเรกทอรีปัจจุบันd/foo.bakไม่ได้
G-Man กล่าวว่า 'Reinstate Monica'

6

สิ่งที่ใกล้เคียงที่สุดที่คุณจะได้รับจากกระบวนทัศน์ของ DOS คือmcp(จากmmvแพ็คเกจ):

mcp 'gmail-meta3*' 'gmail-meta3#1.bak'

หากzshมีให้ใช้งานzmvโมดูลที่สนับสนุนอาจอยู่ใกล้เพียงเล็กน้อย:

autoload -U zmv

zmv -C '(gmail-meta3*)' '$1.bak'

ฉันจะหลีกเลี่ยงlsโดยไม่คำนึงถึง - คำตอบของคุณเองจะปลอดภัยสำหรับช่องว่าง (รวมถึงการขึ้นบรรทัดใหม่)

printf '%s\0' gmail-meta3* | while IFS= read -r -d '' f; do cp -a -- "$f" "$f.bak"; done

หรือบางที

printf '%s\0' gmail-meta3* | xargs -0 -I{} cp -a -- {} {}.bak

ฉันเข้าใจว่าmmvเป็นแพคเกจ แต่ในความคิดเห็นที่คุณพูดคำสั่งนั้นmcpแต่ในคำสั่งที่คุณใช้mmvซึ่งเป็นคำสั่งในmmvแพคเกจ ฉันชอบทิศทางของprintfตัวอย่างและในสคริปต์ที่ขัดเกลาฉันจะรับประกันว่าผ่าน $ 1 และ $ 2 +1 สำหรับการกลิ้งลูกบอล :)
WinEunuuchs2Unix

@ WinEunuuchs2Unix ขอโทษ - mcp / mmv เป็นความคิดสร้างสรรค์ อันที่จริงmcpเป็นเพียงคำพ้องสำหรับmmv -c
steeldriver

ไม่ต้องกังวล ถ้าฉันมีเงินดอลลาร์สำหรับการพิมพ์ผิดทุกครั้งที่ฉันทำฉันจะเป็นเศรษฐีเงินล้าน :) ฉันต้องการคำชี้แจงเกี่ยวกับprintfคำสั่งที่ฉันไม่เคยใช้จริง ๆ คุณกำลังprintf '%s\0' "$1"*จะบอกว่าจะทำงานถ้าgmail-meta3ผ่านเป็นพารามิเตอร์ 1?
WinEunuuchs2Unix

@ WinEunuuchs2Unix ฉันอาจปล่อยให้บริบทการโทรทำคือการทำให้กลมเป็นวงกลมcps gmail-meta3*แล้วเขียนprintf '%s\0"$ @" | ในขณะที่ ... `ในฟังก์ชั่น หรือเพียงใช้for f; do cp -- "$f" "$f.bak"; done(เช่นคำตอบของ xiotaแต่เป็นฟังก์ชั่น)
steeldriver

1
โปรดทราบว่าในขณะที่zmvคุณสามารถใช้โหมด "การแทนที่สัญลักษณ์" ซึ่งฉันพบว่าจะง่ายขึ้นนิดหน่อย:zmv -W -C 'gmail-meta3*' '*.bak'
0x5453

5

โซลูชัน rsync เท่านั้น

หากคุณต้องการสำรองไฟล์คุณสามารถคัดลอกไฟล์ไปยังไดเรกทอรีใหม่

rsync /path/to/dir/Filename* /path/to/backupdirectory

นี้จะคัดลอกFilenameไฟล์จากไป/path/to/dir//path/to/backupdirectory


rsync + filerename

หากคุณต้องการให้ไฟล์สำรองของคุณมีส่วนต่อท้ายสิ่งต่าง ๆ อาจแฮ็คกับrsync...

rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak

สิ่งนี้จะเขียนทับไฟล์ที่มีอยู่ ... ด้วยไฟล์ที่มีอยู่ ( -I) แต่ถ้าเป็น ( -u) ใหม่กว่า (ซึ่งไม่ใช่) และสร้างการสำรองข้อมูลด้วยส่วนต่อท้าย

คุณสามารถทำได้ในไดเรกทอรีเดียวกัน แต่ดีกว่าไม่รวมการสำรองข้อมูลที่มีอยู่

rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak --exclude '*.bak'


ฉันชอบที่rsycncฉันอัปเดต แต่วิธีที่ง่ายกว่าน่าจะเป็นcp Filename* /path/to/backup/dirเพราะไฟล์ไม่จำเป็นต้อง*.bakมีตัวแยกถ้ามันอยู่ในไดเรกทอรีที่แยกต่างหาก
WinEunuuchs2Unix

4

สิ่งนี้ควรทำตามที่ร้องขอ:

cps(){ p="${@: -1}"; for f in "${@:1:$#-1}"; do cp -ai "$f" "${p//\?/$f}"; done  }

การใช้งาน:

cps FILES... pattern
Example 1: cps gmail-meta3* ?.bak
Example 2: cps * save-?
Example 3: cps * bla-?-blubb

ฉันเลือก?เพราะ#จะต้องยกมาเมื่อมันเป็นตัวละครตัวแรกของรูปแบบมิฉะนั้นจะได้รับการยอมรับว่าเป็นจุดเริ่มต้นของความคิดเห็น

ทดสอบ:

$ touch 'test};{bla#?"blubb'
$ cps test* bla-?-blubb
$ ls
test};{bla#?"blubb  bla-test};{bla#?"blubb-blubb


สคริปต์เวอร์ชันก่อนหน้าบางตัวสำหรับการเพิ่มคำต่อท้าย:

คล้ายกับ @ WinEunuuchs2Unix คำตอบ แต่ฉันคิดว่ามีความยืดหยุ่นมากกว่าและไม่แยกวิเคราะห์ls :

cps(){ S="$1"; shift; printf '%s\0' "$@" | xargs -0 -I{} cp -abfS "$S" {} {}; }

.bashrcใส่ในของคุณ

การใช้งาน:

cps SUFFIX FILES...
Example: cps .bak gmail-meta3*

ทางเลือกโดยมีคำต่อท้ายเป็นอาร์กิวเมนต์สุดท้าย ( ผ่านและผ่าน ):

cps(){ S="${@: -1}"; printf '%s\0' "${@:1:$#-1}" | xargs -0 -I{} cp -abfS "$S" {} {}; }

การใช้งาน:

cps FILES... SUFFIX
Example: cps gmail-meta3* .bak


นีซเข้ารหัส แต่ชนิดของฮาร์ดหลังจากหลายทศวรรษของการใช้มาแล้วเป้าหมายไปที่คำสั่งสำเนาสลับไปยังเป้าหมายแล้วที่มา
WinEunuuchs2Unix

เพิ่มฟังก์ชั่นด้วยคำต่อท้ายด้านหลัง
pLumo

ขอบคุณที่ใช้งานง่าย การเรียกว่าคำต่อท้ายนั้นแม่นยำในแบบที่คำตอบของฉันเขียนมัน แต่จริงๆแล้วมันเป็นเป้าหมายหรือปลายทาง copy gmail-meta3* old-meta3*คนอื่นอาจต้องการที่จะใช้: ในคำตอบของฉันฉันไม่สามารถหาวิธีการได้*ชื่อปลายทางเหมือนคำถามที่ฉันขอ ...
WinEunuuchs2Unix

ปัญหาคือที่*ตีความโดยเชลล์ดังนั้นฟังก์ชั่นจะไม่ทราบเกี่ยวกับมัน คุณจะต้องมีตัวละครอื่น ๆ หรืออ้างถึงจากนั้นแทนที่ด้วยชื่อไฟล์เดิมภายในฟังก์ชั่น
pLumo

ฉันเดาว่า#สามารถใช้เป็นสัญลักษณ์แทนได้*หรือไม่ copy filenames# save-#ดังนั้นคุณจึงสามารถพิมพ์ ฉันคิดว่าคุณต้องการให้อักขระไวด์การ์ดเหมือนกันสำหรับแหล่งที่มาและเป้าหมาย
WinEunuuchs2Unix

4

~/.bashrcที่ผมเขียนนี้หนึ่งซับเข้าไปในของฉัน findฉันสามารถโพสต์คำตอบที่ดีกว่าได้มาก คำตอบที่ดียิ่งขึ้นสามารถเขียนเป็นภาษา C หวังว่าคำถาม & คำตอบนี้จะทำให้ลูกบอลกลิ้งไปเพื่อคำตอบที่ดีกว่า:

cps () {
    # cps "Copy Splat", copy group of files to backup, ie "cps Filename .bak"
    # Copies Filename1 to Filename1.bak, Filename2 to Filename2.bak, etc.
    # If Filename1.bak exists, don't copy it to Filename1.bak.bak
    for f in "$1"*; do [[ ! "$f" == *"$2" ]] && cp -a "$f" "$f$2"; done

    # OLD version comments suggested to remove 
    # ls "$1"* | while read varname; do cp -a "$varname" "$varname$2"; done
}
  • for f in "$1"*; do: $1เป็นgmail-meta3พารามิเตอร์และfเป็นรายการของไฟล์ที่ตรงกัน รวมวิธีการนี้สำหรับ gmail-meta3, gmail-meta3-LAB-9999 และอื่น ๆ ให้ทำดังต่อไปนี้
  • [[ ! "$f" == *"$2" ]] &&: $fเหมือนกันกับfด้านบน $2เป็น.bakพารามิเตอร์ที่ผ่าน รวมนี่หมายความว่าหากชื่อไฟล์ไม่ได้อยู่ใน.bak(เพราะเราไม่ต้องการคัดลอก.bakและสร้าง.bak.bak) จากนั้นให้ทำดังต่อไปนี้
  • cp -a "$f" "$f$2"; คัดลอก gmail-meta3 ไปยัง gmail-meta3.bak ฯลฯ
  • done: วนกลับและคว้าชื่อไฟล์ถัดไปในgmail-meta3รายการ *

cps gmail-meta3 .bak ตัวอย่างผลลัพธ์

การใช้คำถามเป็นตัวอย่างต่อไปนี้เป็นลักษณะที่ใช้งานจริง:

───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick   728954 Jun 27 05:46 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ cps gmail-meta3 .bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ 

หมายเหตุ:นี่ใช้-aแฟล็กพร้อมกับcpคำสั่งเพื่อเก็บบันทึกเวลาและทำให้คุณเข้าใจการสำรองข้อมูลไฟล์ได้ดีขึ้น

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


6
คนมักจะไม่แนะนำให้แยกวิเคราะห์ls
qwr

3
ตั้งแต่ที่คุณพูดถึงfindฉันคิดว่าคุณตระหนักถึงอันตรายของการแยกวิเคราะห์ls? แต่ในกรณีของคุณไม่เป็นสิ่งที่จำเป็น: เพียงแค่ทำfor file in "$1"*; do copy -a "$file" "$file$2"; done- นี้เป็นสมบูรณ์ปลอดภัยและง่ายกว่าชนิดของร้ายใด ๆ ผ่านทางlsหรือfindและwhileห่วง
Konrad Rudolph

@ KonradRudolph ขอบคุณสำหรับคำแนะนำของคุณ ฉันดำเนินการและทดสอบข้อเสนอแนะของคุณด้วยการเปลี่ยนแปลงเล็กน้อย
WinEunuuchs2Unix

2

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

$ mkdir backup
$ cp filename* /tmp/rename-backup/
$ rename 's/(filename.*)/$1.bak/' /tmp/rename-backup/*
$ mv /tmp/rename-backup/* ./

หากคุณต้องการมันเป็นสคริปต์คุณสามารถใช้มันได้

cps () {
    mkdir -p /tmp/rename-backup/
    cp "$1"* /tmp/rename-backup/
    rename "s/($1.*)/\$1.$2/" /tmp/rename-backup/*
    mv "/tmp/rename-backup/$1"*".$2" .
}

และคุณสามารถใช้มันได้เช่น:

cps file bak

นี่คือตัวอย่าง

$ ls -l
total 0
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file a
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ab
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ac
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename1
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename2
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename3
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename4
$ cps file bak
$ ls -l
total 0
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file a
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file a.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ab
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file ab.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ac
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file ac.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename1
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename1.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename2
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename2.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename3
-rw-r--r--  1 danny  wheel  0 Jun 26 16:41 filename3.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename4
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename4.bak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.