2016-02-29 4 views
2

Я боролся с этим сценарием Bash около недели, пытаясь сделать то, что кажется самым простым. Я использую fswatch для просмотра данной папки и создания имени файла для любого файла, добавленного к нему в качестве вывода. Этот вывод передается по каналу на xargs, который затем запускает функцию с несколькими командами, которые используют имя файла, переданного fswatch/xargs с заменой переменной/аргумента.Bash: использование аргументов xargs/parallel в функции для переменной подстановки

#!/bin/bash 

compressor() { 
    filepath="filepath" 
    mkdir -m 777 /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING 
    mv ${filepath} /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING 
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath##/} -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath%.*}.mp4 
} 

export -f compressor 

/usr/local/Cellar/fswatch/1.8.0/bin/fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch | 
    xargs -0 -n1 -I'filepath' bash -c compressor 'filepath' 

В простейшей конфигурации, где я по конвейеру вывод в xargs и используется xargs для запуска программы с помощью замены аргументов, все работало отлично. Затем я получил запрос на создание сценария для создания новой папки для каждого добавленного файла, переместите файл в эту папку и запустите команду.

С несколькими командами ничего не работает. Я не могу получить xargs, чтобы передать аргументы функции, чтобы функция могла определять переменную с помощью аргумента и выполнять подстановку переменных в пути к файлу. Если я xargs -I'filepath' command 'filepath' и затем filepath="filepath" внутри функции, я в конечном итоге с mkdir создать файл с именем filepath_PROCESSING, а не аргумент от fswatch замещено в.

Как я могу передать аргумент в функцию с помощью xargs?

+0

Я также попытался это: '#/bin/Баш /USR/местные/Подвал/fswatch/1 .8.0/bin/fswatch -0 -v --event Создано --event MovedTo/Пользователи/leftright/Рабочий стол/Часы | parallel -0 -n1 -q -x -v 'mkdir -m 777 /Users/leftright/Desktop/Watch/"{/.}"_PROCESSING/ \; mv "{}" /Users/leftright/Desktop/Watch/"{/.}"_PROCESSING/ \; /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "Этот компьютер" -jobpath /Users/leftright/Desktop/Watch/"{/.}"_PROCESSING/"{/} "-settingpath/Users/leftright/Documents /CONVERTHQTEST.cmprstng -locationpath /Users/leftright/Desktop/Watch/"{/.}"_PROCESSING/"{/.}".mp4 \; '' – Adam

+0

Очевидно, что это не очень читаемо; если это важно для вопроса, оно должно быть добавлено посредством редактирования, чтобы другие могли его прочитать. – miken32

ответ

0

Две вещи: вы недоразумение how function arguments are passed. Они являются позиционными параметрами (например, 1, 2, 3 и т.д.) так что ваша функция может быть определена что-то вроде этого:

compressor() { 
    filepath="$1" 
    # define a variable rather than including this 5 times 
    process="/Users/lr/Desktop/Watch/${filepath#/}_PROCESSING" 
    mkdir -m 777 "$process" 
    mv "$filepath" "$process" 
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath "$process/${filepath#/}" -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath "$process/${filepath%.*}.mp4" 
} 

Затем, когда вы звоните bash -c, это ожидающие один аргумент (смотрите примечание ниже), но вы передаете ему два. Попробуйте некоторые цитаты и он должен работать:

fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch | 
    xargs -0 -n1 -I filepath bash -c 'compressor "filepath"' 

[ -c will] read and execute commands from the first non-option argument after processing the options, then exit. Any remaining arguments are assigned to the positional parameters, starting with $0.

Bash Reference Manual, Invoking Bash

Очевидно, что я не могу повторить вашу установку, но вот an MVCE, что отлично работает для меня в Баш версии 3 и 4:

#!/bin/bash  
make_noise() { 
    echo "$1" "$1" "$1" "$1" 
} 
export -f make_noise 
echo "foo bar" | xargs -I {} bash -c "make_noise '{}'" 
+0

Спасибо за помощь. Теперь с 'xargs' и' bash -c' появляется следующая ошибка: 'bash: compress: command not found'. Я добавил 'export -f' перед выполнением' fswatch' и 'xargs', но это, похоже, не имеет никакого значения. Я не получаю обратной связи, когда я заменяю 'xargs' на' parallel' даже при использовании флага '-v'. Есть ли еще один компонент для получения функций для работы в качестве аргументов для команды? – Adam

+0

Это отлично работает для меня; см. мое редактирование для минимального тестового примера. – miken32

+0

После того, как он немного изменил ваш оригинальный пример, он отлично работал. Я еще не пробовал с параллелью.Единственная проблема, с которой я сталкиваюсь сейчас, - это то, что fswatch рекурсивно рекурсивно контролирует подкаталоги, поэтому исходный дизайн скрипта создает цикл подкаталогов. Я собираюсь изменить так, чтобы новые файлы отправлялись в другую папку, которую fswatch не отслеживает. Когда я закончил, я опубликую заполненный скрипт. Еще раз спасибо! – Adam

0

Попробуйте:

#!/bin/bash 

compressor() { 
    filepath="$1" 
    mkdir -m 777 /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING 
    mv ${filepath} /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING 
    /Applications/Compressor.app/Contents/MacOS/Compressor -computergroup "This Computer" -jobpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath##/} -settingpath /Users/lr/Documents/CONVERTHQTEST.cmprstng -locationpath /Users/lr/Desktop/Watch/${filepath##/}_PROCESSING/${filepath%.*}.mp4 
} 

export -f compressor 

/usr/local/Cellar/fswatch/1.8.0/bin/fswatch -0 -v --event Created --event MovedTo /Users/lr/Desktop/Watch | 
    parallel -0 compressor 
Смежные вопросы