我用来find -mtime -2
查找过去 24 小时或更短时间内修改的文件。输出看起来像这样。
/home/user/logs/file-2014-08-22.log
/home/user/logs/file-2014-08-23.log
我需要将输出的第一行保存到一个变量,然后将第二行保存到一个单独的变量。我不能只是管它。我知道你可能会建议| grep 22
,23
但这是将运行多次的 bash 脚本的一部分,下次将会有一组不同名称的文件,所以grep
太具体了。能awk
做到这一点吗?如果是这样,怎么办? 。
答案1
假设任何文件名中都没有空格等,有几种方法可以做到这一点。一种是只使用数组:
files=( $(find -mtime -2) )
a=${files[1]}
b=${files[2]}
files
find
将是按顺序输出的所有路径的数组,索引从零开始。你可以从中得到你想要的任何一行。这里我将第二行和第三行保存到a
and中b
,但您也可以直接使用数组元素。
如果您有 GNU find 或其他带有该选项的替代方法printf
是将其与read
和流程替代:
read junk a b junk < <(find -printf '%p ')
这个将 的所有find
输出转换为一行,然后将该行提供为 的输入read
,这会将第一个单词(路径)保存到junk,
第二个中a
,将第三个保存到 中b
,并将该行的其余部分保存到junk
再次中。
同样,您可以引入paste
命令对于任何 POSIX 兼容系统具有相同的效果:
read junk a b junk < <(find -mtime -2 | paste -s)
paste -s
会将其输入转换为单个制表符分隔行,可以read
再次处理。
在一般情况下,如果您愿意多次执行主命令(此处不必要),您可以使用sed
容易地:
find | sed -n 2p
-n
通过使用 抑制普通输出并选择第 2 行进行打印,将仅打印输出的第二行p
。您还可以拼接在一起head
以tail
获得相同的效果,这在很长的文件中可能会更有效。
上述所有内容都具有将第二行和第三行存储到a
and中的相同效果b
,并且所有内容仍然假设您的文件中没有空格、制表符、换行符或任何其他字符。输入字段分隔符 ( IFS
)任何文件名中的值。
但请注意,输出顺序find
未定义,因此“第二个文件”实际上并不是一个有用的标识符,除非您以其他方式组织它们以进行排序。在许多情况下,它可能接近创建顺序,但并非全部。
答案2
通过bash 4.x
,您可以使用地图文件:
$ mapfile -t <<< "$(find -mtime -2)"
$ printf "%s\n" "${MAPFILE[0]}"
/home/user/logs/file-2014-08-22.log
$ printf "%s\n" "${MAPFILE[1]}"
/home/user/logs/file-2014-08-23.log
mapfile
从标准输入读取行到索引数组变量中,默认数组为MAPFILE
。您可以指定数组的名称:
mapfile -t array <<< "$(find -mtime -2)"
-t
选项导致mapfile
从读取的每行中删除尾随换行符。
答案3
无需将自己限制在代码或命令行中找到的已知数量的文件或重复的条目中,您可以使用以下一行(尽管很长)为每个输出分配连续的变量名称find
:
行/脚本:
$ counter=0; for log_file in $(find -mtime -2); do echo $log_file; if [ -f $log_file ]; then ((counter++)); eval var_$counter=`readlink -f $log_file`; fi; done
如果未删除该行,则输出(如常规find
) :echo
.
./logs
./logs/file-2014-08-22.log
./logs/file-2014-08-23.log
但是,在这里我使用选项筛选有效文件if -f ....
(如所述这里),因此保留了所需的信息:
$ echo $counter
2
$ echo $var_1
/home/shadowe/Videos/logs/file-2014-08-22.log
$ echo $var_2
/home/shadowe/Videos/logs/file-2014-08-23.log
因此,顺序变量包含结果的绝对路径find
,并且可以轻松地与现有脚本合并。