立即输入您重命名的最后一个目录

立即输入您重命名的最后一个目录

我有一个目录位于/var/www/html.我用mvfrom重命名了这个目录例子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 进入它与它(请参阅-TGNU 的选项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 ../barcd可以 cd 进入与重命名为不同的bar目录。mvfoo

如果您已设置$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是必要的。当使用包含并遍历符号链接的路径指定新位置时,这可以避免混淆。cdmv..

如果您移动而不仅仅是重命名目录,则必须解决移动不涉及目录重命名的情况:

mv some_dir existing_dir

这将进入some_direxisting_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
}

没有办法将mvand组合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设置任意修改时间是ctimemtime可能最终不同的另一种情况。


1 从技术上讲,对于一个目录,当移动到另一个目录时,您确实会..为那些仍然存储物理“.”的文件系统更改其条目(现在指向新的父目录)。和目录中的“..”条目,而不是在操作系统级别伪造它们。然而,AFAICT,在这种情况下系统仍然不会改变 mtime。

答案4

您可以在调用之前更改目录mv。这使得 shell 对当前工作目录感到困惑。只要源和目标位于同一文件系统上,这对于应用程序来说是无害的,但它会留下变量PWDpwd内置命令和显示旧位置的提示等。要更新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 $movedcd $movedxdg-open $moved(这是我最常用的)等操作。例如:

mvcd () {
  mv "$@" && cd -- $moved[-1]
}

相关内容