切换到当前目录最后修改的子目录

切换到当前目录最后修改的子目录

我有一个应用程序,它定期在不同的目录中生成几个文件,我需要检查生成的最新文件,即在最近的目录(创建或更新)中生成的文件。文件的名称在所有目录中保持不变,因此我只需要一个简单的脚本来将目录更改为最后修改的子目录。

[更新] 通过查看大多数答案,我认为我应该澄清目录名称是动态的(取决于某些用户输入和时间戳),因此我不能假设像 dir[1, 2, 3] 或这样的目录模式相似的

答案1

为此,您不需要任何复杂的管道。此外,您不需要做find任何事情 - 您已经知道每个文件在哪里,只是不知道其中哪个是最新的。这很容易处理。

为了演示,这是我的小测试:

mkdir ./dir1 ./dir2 ./dir3

for d in 1 2 3
do  touch ./dir$d/samefile
    sleep 1
done

这将创建测试集。现在,哪个是最新的?

set -- ./dir[123]/samefile
while [ -e "$2" ]
do  [ "$1" -nt "$2" ] && 
    set -- "$@" "$1"
shift; done
printf %s\\n "$@"

那会告诉我。

输出

./dir3/samefile

touch我可以随意切换操作顺序- 它会给我正确的信息。您所需要的只是函数中的小 shell 循环,如下所示:

newd() { ${2:+:} return 1
    while [ -e "$2" ] && [ -e "$1" ]
    do  [ "$1" -nt "$2" ] && 
        set -- "$@" "$1"
    shift; done
    ${2+false} cd "${1%/*}"
}

请注意,这与演示略有不同,因此如果参数少于两个或任何参数不是实际路径名,它将可靠地失败。

现在你可以这样称呼它:

newd ./path/to/file1 ./path/to/file2

...等等 - 只要你喜欢,就可以有尽可能多的论据。

或者,在我的测试用例中:

newd ./dir[123]/samefile ; pwd

输出

/home/mikeserv/test/dir3

答案2

根据您想要执行的操作以及文件的结构,可能还有其他可能性,例如:

ls -1tq /dir/*/readme.txt | head -n 1

返回在 /dir/ 的任何子目录(非递归)中找到的最新 readme.txt 的全名

* 作为路径的一部分(而不仅仅是作为文件名的一部分)的用法通常不为人所知,我认为值得一提。

file=$( ls -1tq /dir/*/readme.txt | head -n 1 )
cd $( dirname "$file" )

答案3

为了获得更多的便携性,您可以使用perl

$ perl -MList::Util=reduce -le '
    BEGIN { $dir = "." }
    opendir DIR,$dir;
    print shift @{(reduce {$a->[1] > $b->[1] ? $a : $b}
                   map {[$_,(stat($_))[9]]}
                   grep { -d and !/^..?$/ }
                   readdir DIR)}
'
.Skype

更改$dir为您要搜索的任何目录。

它是如何工作的

  • readdir返回 dir 句柄中所有文件和目录的列表opendir
  • grep { -d and !/^..?$/ }:我们得到所有目录、跳过...目录。
  • map {[$_,(stat($_))[9]]}:创建一个数组,它的元素是一个数组引用,有两个元素:
    • 首先是目录名称
    • 第二个是修改时间
  • reduce {$a->[1] > $b->[1] ? $a : $b:像 max 函数一样,我们将数组中的每个元素与第二个元素(即修改时间)进行比较。
  • @{...}取消引用数组,shift获取第一个元素,即目录名称。

答案4

简短的回答:研究man find“时间”选项。这将找到文件,然后使用该-printf选项显示文件的路径,然后可用于cd <path>


一种使用find和提取当前目录及其子目录中最后访问的文件(最近 24 小时内)的 DIR 的方法

lastAccDir="$(find 2>/dev/null .-type f -atime 1 -printf "%a~%h\n" | sort -r | head -n 1 | cut -d~ -f2)"

或与续行相同(更具可读性)

最后一个目录=“$(
找到 2>/dev/null 。 -type f \ -atime 1 -printf "%a~%h\n" \
 |排序-r \
 |头-n 1 \
 |切-d~-f2
)”

请注意,由于-atime 1(过去 24 小时),这可能会导致结果为空

test ! -z "$lastAccDir" && cd "$lastAccDir"
然后检查非空结果,如果不空则移入目录。

相关内容