mv
当我或cp
文件时,我还可以移动或复制文件的目录层次结构吗?
例如,如果 Imv
或cp
dir1/dir2/file
其他地方,它只会mv
或cp
file
。如果我也想mv
或者怎么办cp
dir1/dir2
?不是mkdir -p dir1/dir2
可以用一个命令来完成吗?
答案1
您可以使用cp
的--parents
开关:
$ mkdir -p step1/step2/step3
$ touch step1/step2/step3/file
$ mkdir copy
$ cp --parents step1/step2/step3/file copy
$ ls copy/step1/step2/step3/file
copy/step1/step2/step3/file
mv
但是,没有开关--parents
,但您可以执行以下操作:
$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
这将:
- 找到该文件。
- 将其(及其父级)复制到目的地。
- 删掉原来的。
您可以为此创建一个函数:
mvparents()
{
[[ $# -ne 2 ]] && echo "2 arguments needed." && return
[[ ! -r "$1" ]] && echo "$1 is not readable." && return
[[ ! -d "$2" ]] && mkdir -p "$2"
find $(dirname $1) -name "$(basename $1)" -exec cp --parents {} $2/ \; -delete
}
$ mvparents step1/step2/step3/file copy/
如果您尝试移动多个文件,这可能需要进行一些调整。这是一个示例(在 bash 中工作,但不保证其他 shell):
mvparents()
{
[[ $# -lt 2 ]] && echo "Usage: $0 [source] <source> ... [destination]." && return
# Get the destination directory.
for dest; do true; done
[[ ! -d "$dest" ]] && mkdir -p "$dest"
# Copy the arguments and remove the destination.
parameters=( "$@" )
unset parameters[${#parameters[@]}-1]
# For each source file: find, copy, delete.
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
find $(dirname $source) -name "$(basename $source)" -exec cp --parents {} $dest/ \; -delete
else
echo "$0: $source is not readable."
fi
done
}
嗯......这比我预期的要长一点,但它应该可以完成工作
编辑:作为塞巴斯蒂安·皮耶希在评论中指出,依靠cp
to domv
的工作是相当性能杀手,因为mv
本来不需要复制文件,只需编辑其元数据即可。您可能想将上面的循环替换为:
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
[[ ! -d "$dest/$(dirname $source)" ]] && mkdir -p "$dest/$(dirname $source)"
find $(dirname $source) -name "$(basename $source)" -exec mv {} "$dest/$(dirname $source)" \; -delete
else
echo "$0: $source is not readable."
fi
done
然而,由于这个东西依赖于一个很多关于 的值$PWD
,我要求您在使用它时要非常小心。