我有一个目录,在化石结账中有多个级别的子目录,我想移动到另一个子目录中的另一个位置并保留多级目录结构。
例如,要将a1移动到下面的a2,从中移动(手写为缩写的find命令输出):
a1/
a1/b/
a1/b/files
a1/c/
a1/c/d/
a1/c/d/more-files
a2/
我希望fossil mv --hard a1 a2
导致:
a2/a1/
a2/a1/b/
a2/a1/b/files
a2/a1/c/
a2/a1/c/d/
a2/a1/c/d/more-files
就像普通的unix mv
命令一样。理想情况下,保存mv的历史记录,以便它可以合并到另一个分支中,文件和更多文件的任何更改都是完整的;因为我可以化石删除文件,然后重新添加为新文件,但这是一个比我想要的更丑陋的解决方案。
fossil mv
命令(在Linux上的v1.33中)丢失了多个级别,最终我将来自较低级别子目录的所有文件移动到新位置的顶级目录中。
答案 0 :(得分:1)
一种解决方案是编写一个脚本来单独移动每个directoy,一次移动一个级别,因此它保留了结构。我想向化石开发人员推荐这个功能。我可以将脚本(下面,下面包含另一个依赖脚本)发布到我的github(用户jgbreezer),但是现在,这个脚本(我称之为fossilmvtree)。它会忽略结帐中的文件,而不是化石,并将旧文件/目录留在任何地方(我不相信它会删除它们):
#!/bin/bash
# $1=source tree
# $2=dest. dir
# supports fossil mv options
# moves single source tree as-is to under/new dest.dir (not reducing dir levels to flat structure under dest dir)
exclude=''
usage () {
cat >&2 <<EOF
Usage: fossilmvtree [-x|--exclude= exclude_dirname] source dest"
-x option may be specified multiple times; do not specify full paths, just last
(filename/aka basename) of a directory to exclude from the move.
Command-line arguments are always included.
EOF
}
while [ -z "${1##-*}" ]
do
case "$1" in
-x|--exclude|--exclude=*)
if [[ "${1#--exclude=}" == "$1" ]]
then
# separate arg, '--exclude=' not used
shift
arg="$1"
else
arg="${1#--exclude=}"
fi
excinfo="$excinfo $arg"
# pruning is efficient
exclude="$exclude -type d -name '${arg//\'/\\\'}' -prune -o"
;;
--case-sensitive)
fossilopts="$fossilopts $1 $2"; shift;;
-*)
fossilopts="$fossilopts $1";;
esac
shift
done
echo "excluding paths: $excinfo"
echo "fossil mv options: $fossilopts"
[ $# -eq 2 ] || { usage; exit 1; }
mv="$(which fossilmvrev 2>/dev/null)" || { usage; echo "error:Missing fossilmvrev" >&2; exit 1; }
src="$1"
srcdir="$(basename "$src")"
dst="$2"
if [ -f "$dst" ]
then
# move src to new subdir of dst; otherwise we're renaming and moving
[ -d "$dst" ] || { echo "error:Destination '$dst' exists but is not a directory" >&2; exit 1; }
dst="$dst/$srcdir"
fi
#could set safe PATH (-execdir is cautious of relative/empty paths in $PATH but fossil binary might not be in std.location): PATH=/bin:/usr/bin:/usr/local/bin
eval find "$src" $exclude -type d -printf '%P\\n' | {
while read -r dir
do
[ -z "$dir" ] || [[ "$src/$dir" == "$dst/$dir" ]] && continue
echo
echo "fossil mv $src/$dir/* $dst/$dir/"
mkdir -p "$dst/$dir" || exit 1
find "$src/$dir" -maxdepth 1 \! -type d -exec "$mv" $fossilopts "$dst/$dir" '{}' +
rmdir "$src/$dir" # tidy up, as we only moved the files above (fossil doesn't really manage dirs)
# if rmdir fails due to remaining files, let user manage that (rmdir will complain to stderr if so) -
# likely to be unversioned files they might have forgotten about, shouldn't delete without user's knowledge.
done
}
它只在我的特定化石结账时进行过一次或两次真正的测试,尽管它已准备好成为可重复使用的脚本;请检查差异(建议在其他地方做一个干净的结账并运行它,然后使用“diff -qr”或其他东西对你的常规进行差异检查,然后再检查它本身的行为)。
如果使用-x / exclude选项,请注意,我不确定它是否正常工作。
这取决于fossilmvrev脚本:
#!/bin/sh
# switch order of move arguments around to work with find -exec ... +
opts=''
while [ -z "${1##-*}" ]
do
case "$1" in
--case-sensitive) opts="$opts $1 $2"; shift 2;;
*) opts="$opts $1"; shift;;
esac
done
destdir="$1"
shift
fossil mv $opts "$@" $destdir
答案 1 :(得分:1)
我认为有一个更简单的解决方案 (这是在Windows下,但类似于Linux)
md a2\a1
fossil mv a1 a2/a1 --hard