Звездообразный символ в bash [дубликат]

Monika Restecka спросил: 28 апреля 2018 в 09:07 в: linux

У этого вопроса уже есть ответ:

  • Rename multiple files in shell 4 ответы

У меня небольшая проблема с моим скриптом bash. Я пытаюсь изменить имя файла в текущем каталоге для целых файлов с расширением txt на расширение text. Для примера 1.txt для 1.text

Теперь мой скрипт выглядит следующим образом:

#!/bin/bash
FILES=`ls /home/name/*.txt`
NAME=*.txt
RENAME=*.textfor file in FILES
do 
mv $NAME $RENAME
done

одиночные, двойные кавычки и обратные ссылки, и я получаю ошибки все время.

Есть ли у вас какие-то идеи о том, как получать подстановочные знаки "*" в bash?

Спасибо.

3 ответа

Ignacio Vazquez-Abrams ответил: 28 апреля 2018 в 09:16

Это совсем не так, как вы это делаете.

#!/bin/bash
shopt -s nullglobOLD=.txt
NEW=.text
FILES=(/home/name/*"$OLD")    for file in "${FILES[@]}"
do
  mv "$file" "${file%$OLD}$NEW}"
done
Tom Fenech ответил: 28 апреля 2018 в 09:28

С вашим скриптом возникает ряд проблем. Во-первых, вы не должны запускать ls и пытаться сохранить свой вывод таким образом. Если вы хотите выполнить итерацию по этому файлу, просто сделайте это в цикле:

for file in /home/name/*.txt

Теперь оболочка выполняет всю работу за вас и в качестве бонуса обрабатывает любые странные имена файлов, которые у вас могут быть.

В вашем примере вы перебираете литеральную строку "FILES", а не переменную, но я думаю, что это была просто опечатка.

чтобы изменить имя файла, необходимо использовать расширение параметра для удаления старого, а затем объединить его с новым:

old=txt
new=textfor file in /home/name/*"$old"
do
    mv "$file" "${file%$old}$new"
done

Если возможно, что нет файлов, соответствующих glob, то по умолчанию код /home/name/*.txt не будет расширяться, и ваш цикл будет запускаться только один раз. то у вас есть несколько вариантов:

  • используйте shopt -s nullglob, чтобы /home/name/*.txt расширялся до нуля, а цикл пропускался
  • добавьте явную проверку внутри цикла, чтобы убедиться, что $file существует, прежде чем пытаться mv:

    for file in /home/name/*"$old"
    do
        [ -e "$file" ] || continue
        mv "$file" "${file%$old}$new"
    done
    
  • уль>
Toby Speight Bjjam ответил: 28 апреля 2018 в 11:55
  1. Вы можете использовать имя переименования для переименования имен файлов.

    rename .txt .text /home/name/*.txt
    
  2. И если вы хотите сделать это путем циклизации, вы можете

    for FILE in /data/tmp/*.txt; do
        mv  "${FILE}" "${FILE/.txt/.text}"
    done
    
    литий> ол>
Toby Speight ответил: 28 апреля 2018 в 11:56
Я добавил важную цитату, которую вы пропустили. У вас все еще есть проблема, что подстановка параметров заменит first .txt на имя, а не на последнюю.