2015-12-18 2 views
1

У меня есть скрипт bash, который ставит кучу команд, чтобы сделать каталог в текстовый файл. Затем введите cat s файл в sh для запуска команд. То, что я пытаюсь сделать, - это запустить только команду, если каталог еще не существует.Попытка с помощью команд трубопровода в оператор if

Вот что у меня есть:

Текстовый файл с чем-то вроде этого:

mkdir /path/to/a/directory 
mkdir /path/to/another/directory 
mkdir /path/to/yet/another/directory 

В моем сценарии у меня есть строка, как этот

cat /path/to/my/file.txt | sh 

Но есть способ сделать что-то подобное?

cat /path/to/my/file.txt | if path already exists then go to the next, if not | sh 

Другими словами, я хотел бы пропустить попытку сделать каталог, если путь уже существует.

+2

не может передавать команды в 'if'. Ваш проект звучит чересчур амбициозно. Получите более простую версию и решите, действительно ли это * стоит усилий по перестройке парадигм сценариев оболочки ;-). Традиционный тест на существование dir - это 'if! [[-d "$ dir"]]; то mkdir -p "$ dir"; fi'. Удачи. – shellter

+0

Проблема заключается не в том, что вы не можете выполнить команду 'if' (что вы можете), это то, что вам действительно нужен цикл здесь. – chepner

+0

@chepner: вы * можете * трубить в 'if' заявление !? Прохладный. Можете ли вы дать пример 1/2 лайнера здесь в качестве комментария? Спасибо – shellter

ответ

1

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

Запустите команду, если файл существует:

[ -f /path/to/my/file.txt ] && cat /path/to/my/file.txt | sh 

или для проверки каталогов:

[ -d /path/to/my/directory ] && cat /path/to/my/file.txt | sh 
+0

Это то, что помогло больше всего. Я фактически использовал его как таковой: '[-d/path/to/dir] || mkdir/path/to/dir' Опять же, как упоминалось выше, я фактически не использую mkdir, но я смог включить этот ответ, и я использовал '||', а не '&&', поскольку я только хотел, чтобы он запускался если путь еще не существует. Спасибо! – VanCityGuy

3

Update: ОП с тех пор уточнили, что использование mkdir это всего лишь пример, и что он нужен механизм общего условно выполнять строки из текстового файла, содержащей команду оболочки, на основе, относятся ли команды в существующем каталог или нет:

while read -r cmd dir; do [[ -d $dir ]] || eval "$cmd $path"; done < /path/to/my/file.txt 
  • while цикла считывает текстовый файл, содержащий команд командной строки.
  • read -r cmd dir анализирует каждую строку в первом токене - предполагается, что это команда (mkdir в примере ввода), а остальная часть - путь к каталогу.
  • [[ -d $dir ]] проверяет существование пути каталога, и || только выполняет свой RHS, если тест терпит неудачу, т.е. если каталог делает не существует.
  • eval "$cmd $path" затем выполняет линию; обратите внимание, что использование eval здесь не менее безопасно, чем трубопроводы до sh - в обоих случаях вы должны доверять строкам, представляющим команды. (Использование eval из текущей оболочки Bash означает, что Bash выполнит команду, а не sh, но я предполагаю, что это не проблема.)

Оригинальный ответ, основанный на предположении, что mkdir фактически используется:

Самый простой подход в вашем случае, чтобы добавить опцию -p вашим mkdir звонки, которые будут спокойно игнорировать пытается создать каталог, который уже существует:

mkdir -p /path/to/a/directory 
mkdir -p /path/to/another/directory 
mkdir -p /path/to/yet/another/directory 

Иначе говоря: mkdir -p обеспечивает существование целевой директории, независимо от того, является ли этот реж. уже существует или должен быть создан. (mkdir -p все еще может потерпеть неудачу, например, когда целевой путь является файл, а не реж., Или если у вас недостаточно прав для создания реж.)

Вы можете просто передать файл sh (нет необходимости в cat и трубы, который является менее эффективным):

sh /path/to/my/file.txt  

в случае, если вы не контролируете создание входного файла, вы можете использовать sed вставить -p вариант:

sed 's/^mkdir /&-p /' /path/to/my/file.txt | sh 
+0

Большое вам спасибо, это здорово знать, но я на самом деле не использую mkdir, я использую другой скрипт, который в основном работает как mkdir, но работает в нашей внутренней сети. Этот сценарий, к сожалению, не имеет флага -p, но опять-таки это полезная информация для будущего! – VanCityGuy

+1

@VanCityGuy: Я рад, что вы нашли решение, и мой ответ по-прежнему полезен. В будущем, пожалуйста, укажите все ограничения, а также какие аспекты ввода образца являются случайными, с самого начала. Я добавил общее решение в верхней части моего ответа, которое, надеюсь, также охватывает ваш прецедент. – mklement0

0

Напишите свой собственный mkdir функции.

Предполагая, что ваш файл не использует mkdir -p в любом месте, это должно сработать.

mkdir() { 
    for dir; do 
     [ -d "$dir" ] || mkdir "$dir" 
    done 
} 
export -f mkdir 

sh < file 
+0

Спасибо за это предложение, но оно немного вне меня.Выглядит интересно, хотя, мне нужно будет сделать некоторые исследования в написании моих собственных функций, это может быть очень полезно для других проектов. Спасибо! – VanCityGuy

Смежные вопросы