我有一个目录位于/var/www/html
.我用mv
from重命名了这个目录例子1到 到例子2。
更改名称后如何输入新命名的目录?
你将如何实现这一目标?可以用find
, mmin
,0*60
吗?
我的目标是在一项操作中重命名和输入,而不是两项不同的操作。
理想情况下,我的目标是单行解决方案,而不需要自定义系统中的任何内容。
答案1
您可以将其添加到 .bashrc 或 .bash_aliases 文件中(如果您的 shell 不是,则添加等效文件bash
):
mvcd () {
mv -- "$1" "$2" &&
cd -P -- "$2"
}
然后,重新启动 shell,然后您就可以像这样使用该函数:
mvcd foo bar
假设$2
不是现有目录,否则mv
会移动 $1
进入它与到它(请参阅-T
GNU 的选项mv
来防止这种情况)。
--
标志着选项的结束。mv "$1" "$2"
将会mv "$option_or_source" "$option_or_argument_to_first_option_or_destination"
。mv -- "$1" "$2"
保证$1
和$2
不会被视为选项,即使它们的名称以 开头,-
因此它始终被视为mv -- "$source" "$destination"
.通常,您希望--
在命令被赋予任意参数的地方使用。
-P
(为了身体的cd
目录遍历)是为了防止POSIX shell 的内置默认情况下对路径组件进行特殊处理,..
以便它处理与处理$2
相同的内容mv
。如果没有它,在 中cdmv foo ../bar
,cd
可以 cd 进入与重命名为不同的bar
目录。mv
foo
如果您已设置$CDPATH
(或者它位于 shell 启动时的环境中),则还需要针对该cd
调用禁用它:
mvcd () {
mv -- "$1" "$2" &&
CDPATH= cd -P -- "$2"
}
一些额外的极端情况问题仍然存在:(-
并且在某些 shell 中-2
,+3
)即使在 之后也会得到特殊处理--
。如果您想重命名foo
为-
,请使用mvcd foo ./-
代替。mvcd foo -
答案2
在ksh93
和 中bash
:
$ pwd
/tmp
$ mkdir test_dir
$ mv test_dir another_name
$ cd $_
$ pwd
/tmp/another_name
$_
扩展到前一个命令的最后一个参数。
作为外壳函数:
mvcd () {
mv -- "$1" "$2"
cd -P -- "$_"
}
但你也可以使用
mvcd () {
mv -- "$1" "$2" &&
cd -P -- "$2"
}
因为这样可以避免在失败时尝试更改目录mv
。
需要使用双破折号才能允许以破折号开头的名称。在这些情况下,双破折号将表示命令行选项的结束,并防止名称被解释为选项。
with对于以与所做的相同方式解释路径(“物理上-P
”而不是“逻辑上”)cd
是必要的。当使用包含并遍历符号链接的路径指定新位置时,这可以避免混淆。cd
mv
..
如果您移动而不仅仅是重命名目录,则必须解决移动不涉及目录重命名的情况:
mv some_dir existing_dir
这将进入some_dir
,existing_dir
所以人们必须
cd existing_dir/some_dir
之后将工作目录更改为移动的目录。
以下修改后的 shell 函数可以解决这个问题:
mvcd () {
if [ -d "$2" ]; then
mv -- "$1" "$2" &&
cd -P -- "$2/$1"
else
mv -- "$1" "$2" &&
cd -P -- "$2"
fi
}
或“更短”:
mvcd () {
if [ -d "$2" ] && mv -- "$1" "$2"; then
cd -P -- "$2/$1"
elif mv -- "$1" "$2"; then
cd -P -- "$2"
fi
}
没有办法将mv
and组合cd
成真正的原子操作。必须mv
首先发生,然后是cd
,无论您如何看待它,即使您是用 C 编写的。一个接一个地执行(同时检查 的退出状态mv
)是正确的方法。
答案3
当您重命名文件(目录类型或其他类型)时,您不会修改它,因此最后修改时间不会改变。它是改变状态时间(通过-cmin
而不是进行检查-mmin
)已更新(至少在 Linux 上,但 POSIX 对此不提供任何保证)。
修改的内容是您将文件移出的目录(当其中的条目被删除/重命名时)和移动到的目录(当其中的条目被添加/重命名时)。他们的状态改变时间也将被修改。
因此,如果您想要启发式地查找最近重命名的目录,一种方法是查找具有最新 ctime 且 ctime 与 mtime 不同的文件。
使用 zsh:
ctime_is_mtime() {
zmodload zsh/stat
local -A stat
zstat -H stat -- $REPLY &&
((stat[ctime] == stat[mtime]))
}
cd ./**/*(D/oc^+ctime_is_mtime[1])
glob 限定符解释:
D
不要跳过隐藏文件和目录/
只考虑目录类型的文件oc
按时间排序^
不是+ctime_is_mtime
调用该函数来检查 ctime 与 mtime。
请注意,即使在支持亚秒粒度的文件系统上,时间粒度也只能降至秒。
ctime
修改但不mtime
包括除访问之外的任何元数据修改的其他情况atime
(例如chmod
,,chown
... setfacl
),以及使用touch
设置任意修改时间是ctime
和mtime
可能最终不同的另一种情况。
1 从技术上讲,对于一个目录,当移动到另一个目录时,您确实会..
为那些仍然存储物理“.”的文件系统更改其条目(现在指向新的父目录)。和目录中的“..”条目,而不是在操作系统级别伪造它们。然而,AFAICT,在这种情况下系统仍然不会改变 mtime。
答案4
您可以在调用之前更改目录mv
。这使得 shell 对当前工作目录感到困惑。只要源和目标位于同一文件系统上,这对于应用程序来说是无害的,但它会留下变量PWD
、pwd
内置命令和显示旧位置的提示等。要更新pwd
朋友们,在 zsh 和 bash 中,您可以使用cd .
;但在其他 shell 中,这不会执行任何操作,而您需要这样做cd `pwd -P`
;在这两种情况下,这不会保留有关符号链接的任何信息。
cd /some/where
mv "$PWD" /else/where
cd . # works in bash and zsh; use cd "`pwd`" in other shells
$PWD
如果它不包含任何 shell 特殊字符,则可以省略引号。您不能用作.
的源,mv
因为.
它本身无法移动,移动需要“真实”目录条目。
该解决方案的优点是不需要多次键入任何路径,并且对于mv
的两种操作模式而言,无论其第二个参数是否是现有目录,它都是稳健的。
您可以将其填充到函数中,尽管这种方法的主要好处是它涉及很少的输入并且不会从函数中获得太多好处。如果您确实决定使用某个函数,我建议您使用以下方法之一。
如果你反过来做事,单行解决方案将不得不牺牲很多情况。的最后一个参数mv
可以是现有目录,在这种情况下源将移至此目录并保留其基本名称,也可以不是,在这种情况下最终名称是目标。这是一个处理这两种情况的函数,同时保持简单(这意味着它错过了很多边缘情况)。
mvcd () {
mv "$@" &&
if [ $# -eq 2 ] && [ ! -d "$2" ]; then
cd "$2"
else
shift $(($#-2))
cd "$2/${1##*/}"
fi
}
我使用一个更大、更强大的函数,将变量设置moved
为目标文件列表。它仍然可以被愚弄,但你必须更加努力。我只是费心为 zsh 编写它,但它可以适用于 bash 和 ksh。
function mv {
emulate -LR zsh
setopt extended_glob
local i target=
moved=("$@")
while [[ $moved[1] == -* ]]; do
case $moved[1] in
-t?*) target=${moved[1]#*t};;
--t*=*) target=${moved[1]#*=};;
-t|--t*) target=$moved[2]; shift moved;;
-S|--su) shift moved;;
--) break;;
esac
shift moved
done
if [[ -z $target ]]; then
target=$moved[-1]
moved=($moved[1,-2])
fi
target=${target%%/##}
if [[ -d $target ]]; then
for ((i=1; i<=$#moved; i++)); do
moved[$i]=$target/${${moved[i]%%/##}##*/}
done
else
moved=($target)
fi
command mv "$@"
}
然后,在mv
命令之后,我可以执行诸如ls -ld $moved
、cd $moved
、xdg-open $moved
(这是我最常用的)等操作。例如:
mvcd () {
mv "$@" && cd -- $moved[-1]
}