Динамическая команда mv из сценария оболочки не работает, если в именах файлов есть пробелы

Я искал уже несколько часов, но не могу найти ответа на этот вопрос. Я пытаюсь создать сценарий оболочки в тюрьме FreeNAS 11 (freebsd), который переместит некоторые файлы во вложенную папку. У меня он правильно получает пути, но когда приходит время переместить файлы, он не работает (когда имя файла содержит пробелы).

#!/bin/sh

# Primary dir to scan
SRC_DIR=/mnt/transcode/batch/
WORKING_DIR = "${SRC_DIR}working/"

for FILE in $SRC_DIR*
do

    # only run against files...
    if test -f "${FILE}"
    then
        #FILE_NAME=$(basename "$FILE" | sed 's/ /\\ /g') # replace spaces with escaped space
        #mv "$SRC_DIR""$FILE_NAME" "$WORKING_DIR""$FILE_NAME"
        #mv $SRC_DIR$FILE_NAME $WORKING_DIR$FILE_NAME

        FILE_NAME=$(basename "$FILE")
        mv \""$SRC_DIR""$FILE_NAME"\" \""$WORKING_DIR""$FILE_NAME"\" #wrap each parameter in double quotes

        # copying this output back into terminal works
        #echo mv \""$SRC_DIR""$FILE_NAME"\" \""$WORKING_DIR""$FILE_NAME"\"
    fi

done

Приведенный выше код также содержит несколько дополнительных вещей, которые я тоже пробовал.

При запуске скрипта я получаю следующее сообщение

mv: rename "/mnt/transcode/batch/REDACTED FILE NAME.mkv" to "/mnt/transcode/batch/working/REDACTED FILE NAME.mkv": No such file or directory

Интересно то, что когда я беру вывод echo mv \""$SRC_DIR""$FILE_NAME"\" \""$WORKING_DIR""$FILE_NAME"\" и вставляю его обратно в терминал, он работает отлично.

Я запускаю это через SSH как root. Разрешения целевой папки: drwxrwxr-x+

Я запускаю свой скрипт через ./test.sh (как пользователь root)

Есть ли другой способ сделать это или есть проблема с моим сценарием?

Любая помощь приветствуется.

PS В моей тюрьме нет / bin / bash, не уверен, что это имеет значение.

--Редактировать--

Вот (надеюсь) окончательный код, который я хочу выполнить:

#!/bin/sh

# Primary dir to scan
SRC_DIR=/mnt/transcode/batch/
DEST_DIR = "${SRC_DIR}converted/"
WORKING_DIR = "${SRC_DIR}working/"
DONE_DIR = "${SRC_DIR}orginal/"

# only get files, not directories
#for FILE in `ls -p $SRC_DIR | grep -v /`
for FILE in $SRC_DIR*
do

    # only run against files...
    if test -f "${FILE}"
    then
        FILE_NAME=$(basename "$FILE" | sed 's/ /\\ /g')

        # move the file to the working dir
        mv $SRC_DIR$FILE_NAME $WORKING_DIR$FILE_NAME

        # vars for later
        MEDIA_FILE=$WORKING_DIR$FILE_NAME

        # Get some into about the current file
        AUDIO_CODEC = "$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of csv=s=x:p=0 $MEDIA_FILE)"
        MEDIA_INFO = "$(ffprobe -v error -select_streams v:0 -show_entries stream=height,width -of csv=s=x:p=0 $MEDIA_FILE)"
        VIDEO_HEIGHT = "$(echo "$MEDIA_INFO" | cut -d 'x' -f2)"
        VIDEO_WIDTH = "$(echo "$MEDIA_INFO" | cut -d 'x' -f1)"

        # start up handbrake
        HandBrakeCLI -i $WORKING_DIR$FILE_NAME -o $DEST_DIR${FILE_NAME%.*}.mkv -f av_mkv -m -e x264 -q 22 --vfr --audio-lang-list eng -E copy:$AUDIO_CODEC --crop 0:0:0:0 -w $VIDEO_WIDTH -l $VIDEO_HEIGHT --subtitle-lang-list eng

        # move the file to the done dir
        mv $WORKING_DIR$FILE_NAME $DONE_DIR$FILE_NAME
    fi

done

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
738
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что вы добавляете лишние кавычки к именам файлов.

mv \"foo\" bar

пытается переименовать файл с буквальным названием "foo" (включая кавычки).

Также не используйте ALL_UPPERCASE для своих переменных. ALL_UPPERCASE используется системой (например, HOME) или самой оболочкой (например, RANDOM, PWD).

Я бы сделал так:

src_dir=/mnt/transcode/batch
working_dir = "$src_dir/working"

for file in "$src_dir"/*; do
    # only run against files...
    if test -f "$file"; then
        mv -- "$file" "$working_dir/"
    fi
done

Вы можете mv прямо в каталог, не нужно сначала извлекать базовое имя.


Не проверено, но вот остальная часть вашего скрипта. Я добавил недостающие кавычки, удалил странные дополнения с обратной косой чертой и т. д.

#!/bin/sh

# Primary dir to scan
src_dir=/mnt/transcode/batch
dest_dir = "$src_dir/converted"
working_dir = "$src_dir/working"
done_dir = "$src_dir/orginal"

for src_file in "$src_dir"/*; do
    if test -f "${src_file}"; then
        basename = "${src_file##*/}"
        working_file = "$working_dir/$basename"

        # move the file to the working dir
        mv -- "$src_file" "$working_file"

        # Get some into about the current file
        audio_codec = "$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of csv=s=x:p=0 "$working_file")"
        media_info = "$(ffprobe -v error -select_streams v:0 -show_entries stream=height,width -of csv=s=x:p=0 "$working_file")"
        video_height = "${media_info#*x}"
        video_width = "${media_info%%x*}"

        # start up handbrake
        HandBrakeCLI -i "$working_file" -o "$dest_dir/${basename%.*}.mkv" -f av_mkv -m -e x264 -q 22 --vfr --audio-lang-list eng -E copy:"$audio_codec" --crop 0:0:0:0 -w "$video_width" -l "$video_height" --subtitle-lang-list eng

        # move the file to the done dir
        mv -- "$working_file" "$done_dir/"
    fi
done

Ах, не видел этого, пока не опубликовал дополнительные подробности. Я только что протестировал его, и он работает как отдельный скрипт. Я посмотрю, смогу ли я включить это в свой более крупный сценарий.

SeniorTwinkie 09.09.2018 10:57

Да! Большое спасибо @melpomene - теперь мне просто нужно изучить его и выяснить, где я ошибся

SeniorTwinkie 09.09.2018 11:21

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