Динамическая команда mv из сценария оболочки не работает, когда в именах файлов есть пробелы - PullRequest
0 голосов
/ 09 сентября 2018

Я искал несколько часов, но не могу найти ответ на этот вопрос. Я пытаюсь создать сценарий оболочки в тюрьме 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

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

1 Ответ

0 голосов
/ 09 сентября 2018

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

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
...