Как я могу создать каталоги во время копирования в bash / zsh / ksh? - PullRequest
2 голосов
/ 14 июня 2009

Я часто получаю следующие сообщения, например, при копировании файлов dev в главную ветвь

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.

Ответы [ 2 ]

2 голосов
/ 15 июня 2009

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

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

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

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

source cpmd

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

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

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

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

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

Создается каталог «anothernew», после чего «supplies» копируется с новым именем файла «расходные материалы».

Если все каталоги в месте назначения уже существуют, 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
    # /775851/kak-ya-mogu-sozdat-katalogi-vo-vremya-kopirovaniya-v-bash-zsh-ksh

    # 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
}
1 голос
/ 14 июня 2009

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

Существуют команды, помогающие с этим, взгляните на basename (1) и dirname (1).

...