Jak zmienić nazwę plików ze spacjami za pomocą powłoki Linux?

28

Nazwałem wiele plików ze spacjami i chcę je zastąpić _. Jednak za każdym razem, gdy piszę polecenie w powłoce o nazwie pliku (np. Spring 2011), Powłoka nie rozpoznaje pliku lub katalogu.

Co mogę z tym zrobić? Czy jest jakiś sposób na użycie znaku Unicode dla spacji?

Phil Braun
źródło
do programowej zmiany nazw plików N użyj bashpętli for: zobacz moje rozwiązanie tutaj .
Trevor Boyd Smith

Odpowiedzi:

33

Escape the space, np. Spring\ 2011Lub użyj cudzysłowów, np 'Spring 2011'. W przyszłości zwykle źle jest używać nazw plików ze spacjami w dowolnym systemie * NIX.

Jeśli masz rename, możesz użyć tego:

rename ' ' '_' [filenames...]
Rafe Kettler
źródło
1
Czy wiesz, czy i tak można to zrobić dla wszystkich plików jednocześnie?
3
Dlaczego to zły pomysł? Obowiązkiem programisty jest prawidłowe zarządzanie nazwami plików.
glenn jackman
1
@rafe, naprawdę jest to podatne na błędy, jeśli nie obsługuje poprawnie nazw plików z góry. Dodatkowy wysiłek wiąże się z koniecznością debugowania skryptu, gdy po prostu zapomniałeś podać zmienne zawierające nazwę pliku.
glenn jackman
3
Ta odpowiedź nie działa (przynajmniej na Ubuntu 12.04 LTS). Odpowiedź od unutbu działa jednak dobrze.
DNA
1
to zrobiło tylko pierwsze miejsce dla mnie ... co nie jest pomocne (mam renamewersję 2.23)
Trevor Boyd Smith
30

Jeśli twoje urządzenie ma polecenie zmiany nazwy , spowoduje to zmianę wszystkich spacji na podkreślenia we wszystkich plikach / katalogach w bieżącym katalogu roboczym:

rename 's/ /_/g' *
unutbu
źródło
Potwierdzony do pracy w Ubuntu 12.04
Anthonygore
1
nie działało dla mnie ... dostałem błąd „Zmień nazwę: za mało argumentów”. mam wersję rename --version rename from util-linux 2.23.2.
Trevor Boyd Smith
24

Jeśli nie masz renamelub wolisz używać tylko powłoki:

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

Zepsuty:

  • *\ *wybiera wszystkie pliki ze spacją w nazwie jako dane wejściowe dla forpętli.
  • Cytaty wokół "$f"są ważne, ponieważ wiemy, że w nazwie pliku jest spacja, w przeciwnym razie wyglądałoby to na ponad 2 argumenty mv.
  • ${f//str/new_str}jest specyficzną dla bash funkcją podstawiania łańcucha. Wszystkie wystąpienia strsą zastępowane przez new_str.
blahdiblah
źródło
2
to działa, ale dla mnie zastępuje tylko pierwszą spację. jeśli for f in *\ *; do mv "$f" "${f// /_}"; donego
użyję, zadziała
@billynoah Dobry połów, zaktualizowano.
blahdiblah
@blahdiblah Dziękuję bardzo! Właśnie zaoszczędziłeś mi tyle czasu!
Partyzant
@blahdiblah twoje rozwiązanie jest o wiele bardziej eleganckie niż moje rozwiązanie . dobra robota. Nie sądziłem, że glob pętli for zadziała ... więc zrobiłem glob poza pętlą for.
Trevor Boyd Smith
3

mv "Spring 2011.file" Spring_2011.file powinien powiedzieć linii poleceń, aby wziął cytowany ciąg jako pojedyncze wejście.

rockerest
źródło
To jedyna odpowiedź, jaką mogłem dostać do pracy.
blakeoft,
1

Aby programowo zmienić nazwy plików N, możesz użyć prostej bashpętli for.

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

Jeśli masz mniej niż 5 nazw plików, możesz ręcznie wpisać wszystkie nazwy plików i użyć renamepolecenia, jak sugeruje powyższe rozwiązanie . Ale dla mnie ... Wolę rozwiązanie programowe ... nawet jeśli są tylko 4 pliki.

ps

jeśli nie znasz Bashrozszerzenia parametrów (tj. ${filename// /_}), możesz użyć renamepolecenia:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi
Trevor Boyd Smith
źródło