【问题标题】:How can I create directories during a copy in bash/zsh/ksh?如何在 bash/zsh/ksh 中复制期间创建目录?
【发布时间】:2010-11-02 20:34:24
【问题描述】:

我经常收到以下消息,例如将 dev 文件复制到 master 分支时

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 从末尾开始刮字母。

【问题讨论】:

标签: bash awk screen-scraping zsh ksh


【解决方案1】:

这是我编写的一个函数,可以在 zsh、bash 或 ksh 中运行。

注意: 它已启用调试(它会回显将要运行的命令,而不是执行它们)。如果你注释掉那一行,它实际上会运行它们。

注意尚未经过彻底测试。

要使用它,请将这个脚本放在一个名为 cpmd 的文件中,该文件位于 /usr/local/bin 中(或路径中的其他位置)。要激活它,请在 shell 提示符下键入以下命令(或将其添加到您的启动脚本中 - 对于 bash,它将是 ~/.bashrc):

source cpmd

然后您可以使用如下命令复制文件:

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

目录“不存在”或“newdir”都不存在。创建两个目录,然后将名为“carparts”的文件复制到“newdir”。

如果您在末尾不包含斜杠(“/”),则最后一部分将被视为文件名,并且在此之前的任何不存在的目录都会被创建:

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

创建目录“anothernew”,然后使用新文件名“consumables”复制“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
    # 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
}

【讨论】:

  • @Dennis:我无法在 OS/X 中运行您的代码。我把它放到 /usr/local/cpmd/ 和我的 PATH 中。当我将文件复制到不存在的目录时,它不会被激活。
  • @Masi:我已经用更完整的指示更新了我的答案。您是否将文件放入 /usr/local/cpmd/ 并将该目录添加到您的 PATH 中?我会推荐 /usr/local/bin 。您是否收到任何消息或错误消息?如果它打印出命令但没有运行它们,那是因为你没有注释掉调试行。如果您收到“找不到命令”之类的消息,那是因为您没有获取该文件。有关更多信息,请参阅附加说明。
  • @Dennis:谢谢你的回答!
【解决方案2】:

该错误消息来自 cp 命令,而不是 zsh。如果你想提高输出,你将不得不编写截断和检查路径的逻辑以及检查它是否存在。

有一些命令可以帮助解决这个问题,请查看 basename(1) 和 dirname(1)。

【讨论】:

    猜你喜欢
    • 2012-08-07
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多