338

所以,如果我在我的主目录中并且我想将 foo.c 移动到 ~/bar/baz/foo.c ,但这些目录不存在,有没有办法自动创建这些目录,这样你只需要输入

mv foo.c ~/bar/baz/ 

一切都会好起来的?似乎您可以将 mv 别名为一个简单的 bash 脚本,该脚本将检查这些目录是否存在,如果不存在,则调用 mkdir 然后调用 mv,但我想我会检查是否有人有更好的主意。

4

19 回答 19

350

这个单线如何(在 bash 中):

mkdir --parents ./some/path/; mv yourfile.txt $_

打破它:

mkdir --parents ./some/path
# if it doesn't work; try
mkdir -p ./some/path

创建目录(包括所有中间目录),之后:

mv yourfile.txt $_

将文件移动到该目录($_ 扩展为传递给上一个 shell 命令的最后一个参数,即:新创建的目录)。

我不确定这在其他 shell 中会起作用多远,但它可能会给你一些关于寻找什么的想法。

下面是一个使用这种技术的例子:

$ > ls
$ > touch yourfile.txt
$ > ls
yourfile.txt
$ > mkdir --parents ./some/path/; mv yourfile.txt $_
$ > ls -F
some/
$ > ls some/path/
yourfile.txt
于 2009-02-13T22:22:10.663 回答
73
mkdir -p `dirname /destination/moved_file_name.txt`  
mv /full/path/the/file.txt  /destination/moved_file_name.txt
于 2012-06-21T19:19:06.370 回答
26

另存为名为 mv.sh 的脚本

#!/bin/bash
# mv.sh
dir="$2" # Include a / at the end to indicate directory (not filename)
tmp="$2"; tmp="${tmp: -1}"
[ "$tmp" != "/" ] && dir="$(dirname "$2")"
[ -a "$dir" ] ||
mkdir -p "$dir" &&
mv "$@"

或者将 ~/.bashrc 文件作为替换每个新终端上的默认 mv 的函数放在末尾。使用函数可以让 bash 保留它的内存,而不必每次都读取脚本文件。

function mvp ()
{
    dir="$2" # Include a / at the end to indicate directory (not filename)
    tmp="$2"; tmp="${tmp: -1}"
    [ "$tmp" != "/" ] && dir="$(dirname "$2")"
    [ -a "$dir" ] ||
    mkdir -p "$dir" &&
    mv "$@"
}

示例用法:

mv.sh file ~/Download/some/new/path/ # <-End with slash

这些基于 Chris Lutz 的提交。

于 2012-04-26T03:54:05.923 回答
14

您可以使用mkdir

mkdir -p ~/bar/baz/ && \
mv foo.c ~/bar/baz/

一个自动执行此操作的简单脚本(未经测试):

#!/bin/sh

# Grab the last argument (argument number $#)    
eval LAST_ARG=\$$#

# Strip the filename (if it exists) from the destination, getting the directory
DIR_NAME=`echo $2 | sed -e 's_/[^/]*$__'`

# Move to the directory, making the directory if necessary
mkdir -p "$DIR_NAME" || exit
mv "$@"
于 2009-02-13T21:18:44.997 回答
10

听起来答案是否定的:)。我真的不想为此创建别名或函数,通常是因为它是一次性的,而且我已经在键入mv命令的过程中,但我发现了一些适用于此的方法:

mv *.sh  shell_files/also_with_subdir/ || mkdir -p $_

如果mv失败(dir 不存在),它将创建目录(这是上一个命令的最后一个参数,所以$_有)。所以只需运行这个命令,然后up重新运行它,这一次mv应该会成功。

于 2016-03-14T19:12:25.050 回答
6

最简单的方法是:

mkdir [directory name] && mv [filename] $_

假设我下载了位于我的下载~/download目录my_PDF

我将键入以下命令(确保我当前的工作目录是~/download):

mkdir my_PDF && mv *.pdf $_

如果您想像这样创建子目录,您可以添加-p选项mkdir:(假设我想创建一个名为 的子目录python):

mkdir -p my_PDF/python && mv *.pdf $_
于 2017-07-07T18:49:44.827 回答
6

利用“获取传递给 shell 脚本的最后一个参数”中的技巧,我们可以创建一个简单的 shell 函数,无论您要移动多少文件,该函数都应该工作:

# Bash only
mvdir() { mkdir -p "${@: -1}" && mv "$@"; }

# Other shells may need to search for the last argument
mvdir() { for last; do true; done; mkdir -p "$last" && mv "$@"; }

使用如下命令:

mvdir foo.c foo.h ~/some/new/folder/
于 2020-10-03T19:08:14.567 回答
5

只有当目标路径中的最后一个目录不存在时, rsync命令才能解决问题,例如,~/bar/baz/如果目标路径bar存在但baz不存在,则可以使用以下命令:

rsync -av --remove-source-files foo.c ~/bar/baz/

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
--remove-source-files   sender removes synchronized files (non-dir)

在这种情况下,如果baz目录不存在,将创建它。但是如果两者bar都不baz存在 rsync 将失败:

sending incremental file list
rsync: mkdir "/root/bar/baz" failed: No such file or directory (2)
rsync error: error in file IO (code 11) at main.c(657) [Receiver=3.1.2]

所以基本上它应该是安全rsync -av --remove-source-files的用作mv.

于 2019-02-27T06:58:34.643 回答
4

下面的shell脚本,也许?

#!/bin/sh
if [[ -e $1 ]]
then
  if [[ ! -d $2 ]]
  then
    mkdir --parents $2
  fi
fi
mv $1 $2

这是基本部分。您可能需要添加一点来检查参数,并且您可能希望在目标存在、源目录存在或不存在时改变行为(即不要覆盖不存在的东西) .

于 2009-02-13T21:21:10.077 回答
2

更愚蠢,但工作方式:

mkdir -p $2
rmdir $2
mv $1 $2

使用 mkdir -p 创建包含共享目标文件名的临时目录的目录,然后使用简单的 rmdir 删除该文件名目录,然后将文件移动到新目标。我认为使用 dirname 的答案可能是最好的。

于 2014-07-01T11:46:28.730 回答
2

这将移动foo.cbaz带有父目录的新目录bar

mv foo.c `mkdir -p ~/bar/baz/ && echo $_`

-p选项将根据mkdir需要创建中间目录。
没有-p路径前缀中的所有目录必须已经存在。

反引号内的所有内容都``被执行,并且输出作为命令的一部分返回。
由于mkdir不返回任何内容,因此只会将 的输出echo $_添加到命令中。

$_引用先前执行的命令的最后一个参数。
在这种情况下,它将返回~/bar/baz/传递给mkdir命令的新目录 ( ) 的路径。


我在没有给出目的地的情况下解压缩了一个存档,并且想将除demo-app.zip当前目录之外的所有文件移动到一个名为demo-app.
以下行可以解决问题:

mv `ls -A | grep -v demo-app.zip` `mkdir -p demo-app && echo $_`

ls -A返回所有文件名,包括隐藏文件(除了隐含的.and..)。

管道符号|用于将ls命令的输出通过管道传输到grep命令行、纯文本搜索实用程序)。
-v标志指示grep查找并返回除demo-app.zip.
该文件列表作为 move 命令的源参数添加到我们的命令行中mv。目标参数是传递给mkdir引用的使用$_和输出的新目录的路径echo

于 2020-05-20T22:24:00.947 回答
2

根据另一个答案中的评论,这是我的 shell 函数。

# mvp = move + create parents
function mvp () {
    source="$1"
    target="$2"
    target_dir="$(dirname "$target")"
    mkdir --parents $target_dir; mv $source $target
}

将此包含在 .bashrc 或类似文件中,以便您可以在任何地方使用它。

于 2020-05-27T03:42:55.867 回答
1

代码:

if [[ -e $1 && ! -e $2 ]]; then
   mkdir --parents --verbose -- "$(dirname -- "$2")"
fi
mv --verbose -- "$1" "$2"

例子:

参数:“d1”“d2/sub”

mkdir: created directory 'd2'
renamed 'd1' -> 'd2/sub'
于 2018-06-30T12:45:04.373 回答
1
((cd src-path && tar --remove-files -cf - files-to-move) | ( cd dst-path && tar -xf -))
于 2019-04-17T07:43:52.257 回答
1

在将文件批量移动到新的子目录时,我经常偶然发现这个问题。理想情况下,我想这样做:

mv * newdir/  

该线程中的大多数答案都建议使用mkdirthen mv,但这会导致:

mkdir newdir && mv * newdir 
mv: cannot move 'newdir/' to a subdirectory of itself

我面临的问题略有不同,因为我想全面移动所有内容,并且,如果我在移动之前创建新目录,那么它也会尝试将新目录移动到自身。所以,我通过使用父目录来解决这个问题:

mkdir ../newdir && mv * ../newdir && mv ../newdir .

/警告:在根文件夹 ( )中不起作用。

于 2020-11-02T13:04:25.427 回答
0

我的一个字符串解决方案:

test -d "/home/newdir/" || mkdir -p "/home/newdir/" && mv /home/test.txt /home/newdir/
于 2017-08-23T15:33:42.407 回答
0

install我用linux上的命令完成了这个:

root@logstash:# myfile=bash_history.log.2021-02-04.gz ; install -v -p -D $myfile /tmp/a/b/$myfile

bash_history.log.2021-02-04.gz -> /tmp/a/b/bash_history.log.2021-02-04.gz

唯一的缺点是文件权限被更改:

root@logstash:# ls -lh /tmp/a/b/

-rwxr-xr-x 1 root root 914 Fev  4 09:11 bash_history.log.2021-02-04.gz

如果您不介意重置权限,可以使用:

-g, --group=GROUP   set group ownership, instead of process' current group
-m, --mode=MODE     set permission mode (as in chmod), instead of rwxr-xr-x
-o, --owner=OWNER   set ownership (super-user only)
于 2021-02-04T16:02:23.887 回答
-1

你甚至可以使用大括号扩展:

mkdir -p directory{1..3}/subdirectory{1..3}/subsubdirectory{1..2}      
  • 它创建了 3 个目录(directory1、directory2、directory3),
    • 并且在其中的每一个中都有两个子目录(subdirectory1,subdirectory2),
      • 并且在它们中的每一个中都有两个子子目录(subsubdirectory1 和 subsubdirectory2)。

您必须使用 bash 3.0 或更新版本。

于 2011-04-01T05:11:06.900 回答
-1
$what=/path/to/file;
$dest=/dest/path;

mkdir -p "$(dirname "$dest")";
mv "$what" "$dest"
于 2016-06-30T01:24:39.327 回答