我有一个应用程序,它定期在不同的目录中生成几个文件,我需要检查生成的最新文件,即在最近的目录(创建或更新)中生成的文件。文件的名称在所有目录中保持不变,因此我只需要一个简单的脚本来将目录更改为最后修改的子目录。
[更新] 通过查看大多数答案,我认为我应该澄清目录名称是动态的(取决于某些用户输入和时间戳),因此我不能假设像 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"
然后检查非空结果,如果不空则移入目录。