2009-06-14 6 views
2

я получаю следующие сообщения часто, например, справляясь Dev файлов на мастер-ветвьКак создать каталоги во время копирования в bash/zsh/ksh?

cp: /Users/Masi/gitHub/shells/zsh/dvorak: No such file or directory 
cp: /Users/Masi/gitHub/shells/zsh/dvorak2: No such file or directory 

Я хотел бы спросить о создании заданных папок таким образом, что моя первая команда будет работать, если я отвечу да на вопрос (ы).

Моя попытка в псевдо-коде, когда я пытаюсь скопировать файл в каталог, который не делает существует

if no such a directory exists, then asks users about to create it: 
    if yes, then mkdir directory AND run the initial command again 
    else do noting 

Проблемы

  1. Чтобы изменить предупреждающее сообщение: Какой файл управляет командой «Нет такого файла или каталога»?
  2. Чтобы очистить путь в исходной команде И mkidr Путь без файла: Как очистить путь в исходной команде?
  3. Чтобы очистить от конца с помощью выбранного вами языка, такого как AWK: Как удалить последнее совпадение в пути, когда/является разделителем полей? Я не уверен, как вы можете царапать буквы, начиная с конца с AWK.
+0

Возможно, лучшим заголовком для этого вопроса было бы что-то вроде «Как создать каталоги во время копирования в zsh?» –

ответ

2

Вот функция, которую я написал, которая будет работать в zsh, bash или ksh.

Примечание:Включена отладка (она перекликается с командами, которые она запускала, а не выполняла их). Если вы закомментируете эту строку, она фактически запустит их.

Осторожно: Он не был тщательно протестирован.

Чтобы использовать его, поместите этот скрипт в файл с именем cpmd в /usr/local/bin (или в другом месте на вашем пути). Для того, чтобы активировать его, из командной строки введите следующую команду (или добавить его в свой сценарий запуска - для Баш было бы ~/.bashrc):

source cpmd 

Затем вы можете скопировать файл, используя команду:

cpmd carparts /home/dave/Documents/nonexistent/newdir/ 

Ни один каталог «несуществующий» или «новый» еще не существует. Оба каталога создаются, тогда файл с именем «carparts» копируется в «newdir».

Если вы не включают в себя слэш («/») в конце концов, последняя часть рассматривается как имя файла и любые несуществующие каталоги до этого созданы:

cpmd supplies /home/dave/Documents/anothernew/consumables 

Каталог «anothernew» создается, тогда «расходные материалы» копируются с новым именем «расходные материалы».

Если все каталоги в назначении уже существуют, cpmd действует как обычная команда cp.

function cpmd { 
    # copies files and makes intermediate dest. directories if they don't exist 
    # for bash, ksh or zsh 
    # by Dennis Williamson - 2009-06-14 
    # http://stackoverflow.com/questions/993266/unable-to-make-nosuchdirectory-message-useful-in-zsh 

    # WARNING: no validation is performed on $1 and $2 

    # all cp commands below are hardcoded with -i (interactive) to prevent overwriting 

    if [[ -n $KSH_VERSION ]] 
    then 
     alias local=typeset 
     local func="$0" 
     local lastchar="${2: -1}" 
     readcmd() { read "$2?$1"; } 
    elif [[ -n $ZSH_VERSION ]] 
    then 
     local func="$0" 
     # the following two lines are split up instead of doing "${2[-1]}" 
     # to keep ksh from complaining when the function is loaded 
     local dest="$2" 
     local lastchar="${dest[-1]}" 
     readcmd() { read "$2?$1"; } 
    elif [[ -n $BASH_VERSION ]] 
    then 
    local func="$FUNCNAME" 
     local lastchar="${2:(-1)}" 
     readcmd() { read -p "$1" $2; } 
    else 
     echo "cpmd has only been tested in bash, ksh and zsh." >&2 
     return 1 
    fi 

    local DEBUG='echo' # COMMENT THIS OUT to make this function actually work 

    if [[ ${#@} != 2 ]] 
    then 
     echo "$func: invalid number of parameters 
Usage: 
    $func source destination 

    where 'destination' can include nonexistent directories (which will 
    be created). You must end 'destination' with a/in order for it to 
    specify only directories. Without the final slash, the 'source' will 
    be copied with a new name (the last portion of 'destination'). If you 
    are copying multiple files and 'destination' is not a directory, the 
    copy will fail." >&2 
     return 1 
    fi 

    local dir=$(dirname "$2") 
    local response 
    local nl=$'\n' 

    # destination ($2) is presumed to be in one of the following formats: 
    # .../existdir    test 1 (-d "$2") 
    # .../existdir/existfile test 2 (-f "$2") 
    # .../existdir/newfile  test 3 (-d "$dir" && $lastchar != '/') 
    # .../existdir/newdir/  (else) 
    # .../newdir/newdir/  (else) 
    # .../newdir/newfile  (else) 

    if [[ -d "$2" || -f "$2" || (-d "$dir" && $lastchar != '/') ]] 
    then 
     $DEBUG cp -i "$1" "$2" 
    else 
     if [[ $lastchar == '/' ]] 
     then 
      dir="$2" 
     fi 
     local prompt="$func: The destination directory...${nl} ${dir}${nl}...does not exist. Create? (y/n): " 
     while [[ -z $response ]] 
     do 
      readcmd "$prompt" response 
      case $response in 
       y|Y) response="Y" ;; 
       n|N) ;; 
       *) response= 
        prompt="$func: Invalid response.${nl} Create destination directory? (y/n): ";; 
      esac 
     done 
     if [[ $response == "Y" ]] 
     then 
      $DEBUG mkdir -p "$dir" && $DEBUG cp -i "$1" "$2" 
     else 
      echo "$func: Cancelled." >&2 
     fi 
    fi 
} 
+0

@ Dennis: Я не могу запустить ваш код в OS/X. Я поместил его в/usr/local/cpmd/и в мою PATH. Он не активируется, когда я копирую файл в каталог, который не существует. –

+0

@Masi: Я обновил свой ответ с более полными инструкциями. Вы поместили файл в/usr/local/cpmd/и добавили этот каталог в свой PATH? Я бы порекомендовал/usr/local/bin. Получали ли вы сообщения или сообщения об ошибках? Если он распечатывал команды, но не запускал их, это потому, что вы не прокомментировали строку отладки. Если вы получили сообщение типа «команда не найдена», это связано с тем, что вы не отправили файл. Дополнительные сведения см. В дополнительных инструкциях. –

+0

@ Dennis: Спасибо за ваш ответ! –

1

Это сообщение об ошибке происходит от команды cp, а не zsh. Если вы хотите улучшить выход, вам придется написать логику для усечения и изучения пути, а также проверить, существует ли она или нет.

Есть команды, которые помогут в этом, посмотрите на basename (1) и dirname (1).

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