我们的 1 个站点有 94 台 PC。有一个文件夹,我们需要检查每台电脑上该文件夹中最旧的文件。
我可以循环运行一个包含所有 IP 的 .txt 文件,但我不知道如何检查和获取最旧的文件并将它们添加到 log.txt 中。我需要该日志中该文件的名称。
while read line; do
IP=$(echo $line | cut -d ';' -f 2)
NAME=$(echo $line | cut -d ';' -f 1)
smbclient '\\'$IP'\C$' -W *** -U ***%*** -c "cd \*****\*****; get TheOldestFile" >> log.txt
使用 smbclient 可以做到这一点吗?
答案1
鉴于 smbclient 命令集没有实现完整的 shell,我最好的想法(除了 smbounting 共享和使用本地 shell 实用程序)是“解析 ls”。
在较高级别上,您可以将单个 smbclient 命令替换为两个命令:
smbclient ... dir
-- 获取文件列表smbclient ... get
-- 获取最旧的文件
由于我没有与您类似的环境,因此以下是我要替换的“内容”:
filename=$(smbclient '\\'$IP'\C$' -W *** -U ***%*** -c "cd \*****\*****; dir" | awk -f parse-smbclient-ls)
smbclient '\\'$IP'\C$' -W *** -U ***%*** -c "cd \*****\*****; get $filename"
其中 parse-smbclient-ls 的内容将是:
BEGIN {
"date +%s" | getline oldesttime
}
/ N / {
# size thu mar dd dd:dd:dd dddd
if (match($0, / N +[[:digit:]]+ +[[:alpha:]]{3} [[:alpha:]]{3} +[[:digit:]]+ [[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2} [[:digit:]]{4}$/)) {
timestamp=sprintf("%s %s %s %s %s", $(NF-4), $(NF-3), $(NF-2), $(NF-1), $NF)
filename=substr($0, 3, RSTART-3)
# trim trailing whitespace -- *** hope the real filename doesn't end in whitespace
sub(/ +$/, "", filename);
("date --date='"timestamp"' +%s") | getline seconds
if (seconds < oldesttime) {
oldesttime=seconds
oldestfile=filename
}
}
}
END {
print oldestfile
}
单步执行该 awk 脚本:
- 将当前最旧的日期值初始化为当前时间;希望最旧的文件至少有一秒旧
- 如果该行匹配
/ N /
,那么我们似乎正在查看一个常规文件(相对于目录) - 如果该行与给定的正则表达式匹配(它尝试小心地仅匹配 N、字节大小和时间戳,后跟该行的末尾
$
),则 - 提取时间戳
- 提取文件名
- 删除文件名中的尾随空格
- 要求 GNU date 将文件的时间戳转换为秒
- 如果当前文件比我们现有的文件旧,请保存时间戳和文件名
- 最后,打印最旧的文件名
请注意,我知道这至少有两个问题:
- 如果实际文件名以空格结尾(这是完全合法的,即使在 Windows 上我相信也是如此),那么这个过程将会失败二方式 -- awk 脚本会修剪空格本身,并且命令替换也会去除尾随空格。
- 包含(某种)特殊字符的文件被重命名;例如,当我创建一个名为 的文件时
foo$'\n'bar
,smbclientdir
命令反而向我显示:FKCEWC~I
作为文件名。