ฉันจะเปลี่ยนชื่อไฟล์ด้วยช่องว่างโดยใช้เปลือก Linux ได้อย่างไร


28

_ผมตั้งชื่อจำนวนไฟล์ที่มีช่องว่างในพวกเขาและฉันต้องการที่จะเปลี่ยนพื้นที่ที่มี อย่างไรก็ตามทุกครั้งที่ฉันเขียนคำสั่งในเชลล์ด้วยชื่อไฟล์ (เช่นSpring 2011) เชลล์จะไม่รู้จักไฟล์หรือไดเรกทอรี

ฉันจะทำอะไรเกี่ยวกับเรื่องนี้? มีวิธีการใช้อักขระยูนิโค้ดสำหรับช่องว่างหรือไม่?


สำหรับโปรแกรมเปลี่ยนชื่อไฟล์ N, ใช้bashสำหรับวง: ดูวิธีการแก้ปัญหาของฉันที่นี่
เทรเวอร์บอยด์สมิ ธ

คำตอบ:


33

หนีพื้นที่เช่นหรือคำพูดที่ใช้เช่นSpring\ 2011 'Spring 2011'ในอนาคตมันเป็นความคิดที่ไม่ดีที่จะใช้ชื่อไฟล์ที่มีช่องว่างในนั้นบน * NIX

หากคุณมีrenameคุณสามารถใช้สิ่งนี้:

rename ' ' '_' [filenames...]

1
คุณรู้หรือไม่ว่ามีการทำเช่นนี้สำหรับไฟล์ทั้งหมดในครั้งเดียว?

3
ทำไมมันเป็นความคิดที่ไม่ดี? เป็นความรับผิดชอบของโปรแกรมเมอร์ที่จะจัดการกับชื่อไฟล์อย่างถูกต้อง
เกล็นแจ็คแมน

1
@rafe ข้อผิดพลาดมีแนวโน้มที่จะไม่จัดการกับชื่อไฟล์อย่างถูกต้องล่วงหน้า ความพยายามพิเศษเกิดขึ้นเมื่อคุณต้องดีบักสคริปต์เมื่อคุณลืมอ้างข้อความตัวแปรที่มีชื่อไฟล์
เกล็นแจ็คแมน

3
คำตอบนี้ดูเหมือนจะไม่ทำงาน (บน Ubuntu 12.04 LTS อย่างน้อย) คำตอบจากunutbuทำงานได้ดีแม้ว่า
DNA

1
นี่เป็นเพียงช่องว่างแรกสำหรับฉัน ... ซึ่งไม่เป็นประโยชน์ (ฉันมีrenameรุ่น 2.23)
Trevor Boyd Smith

30

หากเครื่องของคุณมีคำสั่งเปลี่ยนชื่อสิ่งนี้จะเปลี่ยนช่องว่างทั้งหมดเป็นขีดล่างในไฟล์ / dirs ทั้งหมดในไดเรกทอรีการทำงานปัจจุบัน:

rename 's/ /_/g' *

ได้รับการยืนยันให้ทำงานใน Ubuntu 12.04
anthonygore

1
ใช้งานไม่ได้สำหรับฉัน ... ฉันพบข้อผิดพลาดของ "เปลี่ยนชื่อ: มีข้อโต้แย้งไม่เพียงพอ" rename --version rename from util-linux 2.23.2ฉันมีรุ่น
เทรเวอร์บอยด์สมิ ธ

24

หากคุณไม่มีrenameหรือต้องการใช้เพียงเปลือก:

for f in *\ *; do mv "$f" "${f// /_}"; done

พังทลายลง:

  • *\ *เลือกไฟล์ทั้งหมดที่มีช่องว่างในชื่อเป็นอินพุตสำหรับการforวนซ้ำ
  • คำพูดที่อยู่รอบ ๆ"$f"ที่มีความสำคัญเพราะเรารู้ว่ามีช่องว่างในชื่อไฟล์และมิฉะนั้นก็จะปรากฏเป็น 2+ mvข้อโต้แย้ง
  • ${f//str/new_str}เป็นคุณลักษณะการแทนที่สตริงที่เฉพาะเจาะจงของ bash ทุกกรณีจะถูกแทนที่ด้วยstrnew_str

2
มันใช้งานได้ แต่สำหรับฉันมันแทนที่พื้นที่แรกเท่านั้น ถ้าฉันใช้for f in *\ *; do mv "$f" "${f// /_}"; doneมันใช้งานได้
billynoah

@billynoah จับดีอัปเดตแล้ว
blahdiblah

@blahdiblah ขอบคุณมาก! คุณเพิ่งช่วยฉันเวลามาก!
กองโจร

@blahdiblah วิธีการแก้ปัญหาของคุณเป็นวิธีวิธีที่สง่างามมากกว่าการแก้ปัญหาของฉัน งานที่ดี ฉันไม่คิดว่าห่วง for glob จะทำงานได้ ... ดังนั้นฉันจึงทำ glob นอกวง
เทรเวอร์บอยด์สมิ ธ

3

mv "Spring 2011.file" Spring_2011.file ควรบอกให้ command-line ใช้สตริงที่ยกมาเป็นอินพุตเดี่ยว


นี่เป็นคำตอบเดียวที่ฉันสามารถไปทำงานได้
blakeoft

1

หากต้องการเปลี่ยนชื่อไฟล์ N โดยทางโปรแกรมคุณสามารถใช้การbashวนรอบแบบง่าย

#!/bin/bash

set -eux

# find all your files by using a `grep` pattern
pattern="insert_filename_pattern_here" # you must enter your filename pattern here

# create an array of filenames and split on newlines
IFS=$'\n'
tmp=($(ls | grep ${pattern}))
unset IFS

# for each filename
for filename in "${tmp[@]}"; do
    # rename the filename to use "_" character instead of a " " character
    mv -v "${filename}" "${filename// /_}"
done

ถ้าคุณมีน้อยกว่า 5 ชื่อไฟล์แล้วคุณสามารถพิมพ์ในชื่อไฟล์ทั้งหมดและใช้renameคำสั่งเหมือนข้างต้นแก้ปัญหาให้เห็น แต่สำหรับฉัน ... ฉันชอบโซลูชันการเขียนโปรแกรม ... แม้ว่าจะมีเพียง 4 ไฟล์

PS

หากคุณไม่คุ้นเคยกับBashการขยายพารามิเตอร์ (เช่น${filename// /_}) คุณสามารถใช้renameคำสั่ง:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.