Как я делаю оболочку для распознавания имен файлов, возвращенных 'ls-A' команда, и эти имена содержат пробелы?

Это - часть сценария, который я использую для переименования файлов, возвращенных ls -A:

for FILE in `ls -A`
do
        ext=${FILE##*.}
        NUM=$(($NUM+1))
        NEWFILE=`echo $2_$NUM.$ext | sed 's/ /_/g'`

        mv "$FILE" "$NEWFILE"
done

Но не может найти имена с пространством! Параметр за 2$ не может быть причиной ошибки, почему я когда-либо ступаю имя без пространства в качестве параметра, и этот сценарий берет то имя, и переименуйте все файлы в папке так для разрешения им пронумерованный и не изменяйте расширение файла. К сожалению, это не переименовывает файлы с пробелами на имя. Кто-то может помочь мне?

3
задан 1 May 2014 в 10:44

5 ответов

ls -A для меня пишет несколько имен файлов на одной строке, разделенной пробелом. Если бы Вы пытались добавить -1 как в ls -A1, который произвел бы одно имя файла на строку и мог бы работать лучше на Вас.

я столкнулся с теми же проблемами с пробелами в имени файла, особенно когда использование находит, но разделение имен с нулевым символом обрабатывает пробелы & новые строки в именах файлов:
find (...) -print0 | xargs -0 (do stuff here)

, Но, если Вы просто хотите переименовать файлы, Вы могли бы рассмотреть man rename, это может сделать вещи как:

For example, to rename all files matching "*.bak" to strip the extension,
you might say
     rename 's/\.bak$//' *.bak
To translate uppercase names to lower, you'd use
     rename 'y/A-Z/a-z/' *

Или для gui решения для нескольких каталогов Thunar имеет хороший интерфейс Rename Multiple Files, который может сделать нумерацию, как Вы описываете также. Я просто попробовал некоторые имена файлов пробелами, объединенными с находкой к Thunar, и это, кажется, работает:
find . -type f -print0 | xargs -0 thunar -B

2
ответ дан 17 November 2019 в 09:08

for выполняет итерации [более чем 114] слов , слова разграничены пробелом. Вы не должны выполнять итерации по выводу ls, необходимо использовать * .*:

for file in * .* ; do
    if [[ $file = . || $file = .. ]] ; then
        continue
    fi
    # ...
done
10
ответ дан 17 November 2019 в 09:08

Можно включать скрытые файлы ('точечные файлы') в ударе '*' шарик оболочки путем установки dotglob опция

shopt -s dotglob
for file in *
do 
  echo "$file"
done

оболочки, например, для каталога, который содержит file, file with spaces и .hidden file (последний из которых скрыт и имеет пространство), это производит

file
file with spaces
.hidden file

, можно хотеть добавить nullglob опция также для предотвращения состояния ошибки в случае, что каталог пуст - посмотрите превосходное BashFAQ/004. Не забудьте заключать переменную в кавычки "$file", и также это - лучшая практика для не использования всех заглавных букв для имен переменной.

6
ответ дан 17 November 2019 в 09:08

Как насчет:

ls -A | while read fname
do
    echo "$fname" # your code goes here
done

Передача по каналу ls силы это для отправки 1 имени файла на строку, read тогда принимает строку в переменную fname.

0
ответ дан 17 November 2019 в 09:08

В случае, если Вы еще не выяснили, анализируя ls Bad Idea®. Если Вы не можете знать, что Ваши имена файлов всегда будут нормальны (Вы обычно не можете), необходимо смочь иметь дело с именами файлов, содержащими:

  • пробелы и вкладки
  • последовательные пробелы или вкладки
  • новые строки (\n)
  • возвраты каретки (\r)
  • обратные косые черты (\)

Все вышеупомянутое позволяется ядром Linux (и, как гарантируют, сведут Вашего системного администратора с ума). Следующие два метода могут иметь дело с любой комбинацией вышеупомянутого. Я использую cp file directory/ как команда в качестве примера):

  1. Использовать find и -exec опция, {} будет заменен каждым найденным файлом или каталогом.

    find . -exec cp {} directory/
    
  2. Передайте результаты находки по каналу к xargs поскольку пустой указатель разделил строки (-print0), скажите xargs считать разделенный пустой указатель (-0) и скажите этому заменять {} с каждым файлом/именем каталога (-I {}).

    find . -print0 | xargs -0 -I {} cp {} directory/
    
  3. Используйте одну только оболочку, чтобы соответствовать dotfiles также, активироваться dotglob

     shopt -s dotglob
     for i in *; do cp -v "$i" directory/; done
    
  4. Объедините питание find и универсальность оболочки

    find . -print0 | while IFS= read -r -d '' i; do cp "$i" directory/; done
    

    IFS= отключает разделение в пробелах, -r отключает Escape обратной косой черты (позволяет обратным косым чертам рассматриваться буквально), -d '' устанавливает разделитель записей (строки, если Вам нравится) к пустому указателю.

2
ответ дан 17 November 2019 в 09:08

Другие вопросы по тегам:

Похожие вопросы: