将文件复制到目标并创建目标(如果不存在)

Copy files to destination and create destination if does not exist

我正在写一个bash脚本来复制一个多个所有 文件到目的地,如果目的地不存在则创建。

我已经完成了这个 solution 但它没有完成我的要求。

我的代码(由于 idk 什么原因不起作用):

# copy files and make a directory if does not exist
mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    # loop over all arguments
    for file in "$@"
    do
        # if file is last argument (directory) then break loop
        if [ "$file" == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

我希望所有这些命令都能正常工作:

# copies "text.txt" to "testdir" (testdir may or may not exist so it must be created first)
$ mkcp test.txt ~/desktop/testdir

# copies "test1.txt" and "test2.txt" to "testdir" (conditions are same)
$ mkcp test1.txt test2.txt ~/desktop/testdir

# copies "all files" to "testdir" (conditions are same)
$ mkcp * ~/desktop/testdir

如果有任何其他解决方案可以完成我的要求,我也可以。

注:mkcp函数存储在.zshrc.

这是我建议的主要更改:

mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    # loop over all arguments
    for file in "$@"
    do
        # if file is last argument (directory) then break loop
        if [ "$file" == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

我不清楚您是如何收到错误消息的mkcp:9: = not found;要调试它,我需要查看您修改后的代码。 OTOH,我不相信调试会特别有建设性。

这个命令有错误

# copies "all files" to "testdir" (conditions are same)
$ mkcp * ~/desktop/testdir

您正在将字符串“*”作为命令传递给自定义函数,因此当您发送 *mkcp * 你实际上是在说 "cp -R * /path" 其中 * 只是一个字符串,而不是 'all'.

您可以尝试这样做:

mkcp() {
    # last argument is destination
    dir="${@: -1}"
    # create directory if does not exist
    mkdir -p "$dir"
    
    # loop over all arguments
    for file in "$@"
    do
        if [[ "${file}" == "*" ]]; then
            LIST_FILE=$(ls $dir)
            for i in $LIST_FILE
            do
               cp $i $dir
            done
            break
        fi
        # if file is last argument (directory) then break loop
        if [ file == "$dir" ]; then
            break
        fi
        # else keep copying files
        cp -R "$file" "$dir"
    done
}

如果您需要 'debug' 脚本正在执行什么,请尝试 运行 脚本为:

bash -x mkcp * ~/desktop/testdir

-x 将如何执行脚本的每个步骤。

在我意识到这是一个 zsh 问题之前,我添加了这个 bash 答案。没有删除它,希望其他人发现它有用。


您可以使用 ${var:offset:length} 扩展获取位置参数的子列表。请参阅手册中的 Shell Parameter Expansion

也许是这样:

mkcp() {
    local dir="${@: -1}"

    mkdir -p "$dir"

    for file in "${@:0:$#}"     # all but last
    do
        cp -vR "$file" "$dir"
    done
}

事实上,它可以更简单,假设你有 GNU cp 和 -t 选项:

mkcp() {
    local dir="${@: -1}"
    mkdir -p "$dir"
    cp -t "$dir" -vR "${@:0:$#}"
}

我添加了 cp 的 -v 选项以更加详细,因此您可以看到正在复制哪些文件。

您假设最后一个参数必须是一个目录,如果不存在这样的目录,则应该创建一个。在 zsh 中,我会这样做:

mkcp() {
  local destdir=$@[-1]
  if [[ -f $destdir ]]
  then
    echo Missing destination directory 2>&1 
    return 1
  else
    mkdir -p $destdir
    if [[ -d $destdir ]]
    then
      cp "$@"
    else
      echo Can not create $destdir
      return 1
    fi
  fi
}

问题不在于复制(普通的cp命令就可以完成,不需要循环),所以这里的重点是错误检查。

请注意,使用我的方法,开关可以隐式传递给 cp,例如

mkcp -r foo bar baz

也递归复制子目录,并且

mkcp -rv foo bar baz

另外打印复制的文件的名称。