Làm cách nào để đổi tên các tệp có khoảng trắng bằng shell Linux?


28

Tôi đặt tên cho một số tệp có khoảng trắng trong đó và tôi muốn thay thế khoảng trắng bằng _. Tuy nhiên, mỗi khi tôi viết một lệnh trong shell với tên tệp (ví dụ Spring 2011), shell sẽ không nhận ra tệp hoặc thư mục.

Những gì tôi có thể làm gì về điều này? Có cách nào để sử dụng ký tự unicode cho một khoảng trắng không?


để đổi tên các tệp N theo chương trình, hãy sử dụng bashvòng lặp for: xem giải pháp của tôi ở đây .
Trevor Boyd Smith

Câu trả lời:


33

Thoát khỏi không gian, ví dụ Spring\ 2011, hoặc sử dụng dấu ngoặc kép, ví dụ 'Spring 2011'. Trong tương lai, thông thường nên sử dụng tên tệp có khoảng trắng trong bất kỳ * NIX nào.

Nếu bạn đã có rename, bạn có thể sử dụng điều này:

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

1
Bạn có biết có cách nào để làm điều này cho tất cả các tệp cùng một lúc không?

3
Tại sao nó là một ý tưởng tồi? Lập trình viên có trách nhiệm xử lý tên tập tin đúng cách.
glenn jackman

1
@rafe, thực sự đó là lỗi không xử lý tên tập tin đúng cách lên phía trước. Nỗ lực thêm đến khi phải gỡ lỗi một tập lệnh khi bạn chỉ đơn giản là quên trích dẫn các biến chứa tên tệp.
glenn jackman

3
Câu trả lời này dường như không hoạt động (ít nhất là trên Ubuntu 12.04 LTS). Câu trả lời từ unutbu hoạt động tốt mặc dù.
DNA

1
điều này chỉ làm không gian đầu tiên cho tôi ... không hữu ích (tôi có renamephiên bản 2.23)
Trevor Boyd Smith

30

Nếu máy của bạn có lệnh đổi tên , thì điều này sẽ thay đổi tất cả các khoảng trắng thành dấu gạch dưới trong tất cả các tệp / thư mục trong thư mục làm việc hiện tại:

rename 's/ /_/g' *

Xác nhận hoạt động trong Ubuntu 12.04
anthonygore

1
không làm việc cho tôi ... tôi đã gặp lỗi "đổi tên: không đủ đối số". i có phiên bản rename --version rename from util-linux 2.23.2.
Trevor Boyd Smith

24

Nếu bạn không có rename hoặc chỉ thích sử dụng vỏ:

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

Hỏng:

  • *\ *chọn tất cả các tệp có khoảng trắng trong tên của chúng làm đầu vào cho forvòng lặp.
  • Các trích dẫn xung quanh "$f"rất quan trọng vì chúng ta biết có một khoảng trắng trong tên tệp và nếu không nó sẽ xuất hiện dưới dạng 2+ đối số đểmv .
  • ${f//str/new_str}là một tính năng thay thế chuỗi cụ thể bash. Tất cả các trường hợp strđược thay thế bằng new_str.

2
Điều này hoạt động nhưng đối với tôi nó chỉ thay thế không gian đầu tiên. nếu tôi sử dụng for f in *\ *; do mv "$f" "${f// /_}"; donenó hoạt động
billynoah

@billynoah Bắt tốt, cập nhật.
blahdibmus

@blahdiblah Cảm ơn bạn rất nhiều! Bạn vừa tiết kiệm cho tôi rất nhiều thời gian!
Du kích

@blahdiblah giải pháp của bạn là cách thanh lịch hơn so với giải pháp của tôi . làm tốt lắm. Tôi không nghĩ rằng vòng lặp for sẽ hoạt động ... vì vậy tôi đã thực hiện vòng tròn bên ngoài vòng lặp for.
Trevor Boyd Smith

3

mv "Spring 2011.file" Spring_2011.file nên báo cho dòng lệnh lấy chuỗi trích dẫn làm đầu vào đơn.


Đây là câu trả lời duy nhất mà tôi có thể làm việc.
blakeoft

1

Để đổi tên các tệp N theo chương trình, bạn có thể sử dụng một bashvòng lặp đơn giản .

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

Nếu bạn có ít hơn 5 tên tệp, thì bạn có thể nhập thủ công tất cả tên tệp và sử dụng renamelệnh như giải pháp trên gợi ý. Nhưng đối với tôi ... tôi thích giải pháp lập trình hơn ... ngay cả khi chỉ có 4 tệp.

ps

nếu bạn không quen với BashMở rộng tham số (nghĩa là ${filename// /_}), bạn có thể sử dụng renamelệnh:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.