[[ ! -f seen ]] && touch seen && ls -i seen > seen
file=$(find . -type f -printf %i"\n" | sort | join -j 1 -v 1 - seen | shuf -n 1)
echo $file >> seen
sort -o seen seen
find -inum $file -exec cat {} \; #or whatever you want to do with the file
文件是否在您的搜索路径中无关紧要seen,如果是,则只需将其自己添加inode到自身以被筛选掉。
对于单个检查会话,只需遍历列表
[[ ! -f seen ]] && touch seen && ls -i seen > seen
sort -o seen seen
list=$(mktemp)
find . -type f -printf %i"\n" | sort | join -j 1 -v 1 - seen | shuf -o $list
while read file; do
echo $file >> seen
find -inum $file -exec sh -c 'echo -e "$1 contains ....\n"; cat "$1"; echo -e "\n\n"' sh {} \;
sleep 1
done < $list
find ./ -type f | shuf |
while IFS= read -r pathname; do
if ! grep -xF "$pathname" ~/shuffled.txt; then
# do work with "$pathname"
echo "$pathname" >> ~/shuffled.txt
fi
done
在这里它将跟踪洗牌的文件。
@使用mlocate
每次使用find都需要更多时间...相反,最好在此处使用 mlocate 实用程序...
#!/bin/bash
set -e
sudo updatedb -U ./ -o mlocate.db && locate -d mlocate.db '*' | shuf |
while IFS= read -r pathname; do
if [ -f "$pathname" ]; then
if ! grep -xF "$pathname" ~/shuffled.txt; then
# do work with "$pathname"
echo "$pathname" >> ~/shuffled.txt
fi
fi
done
您的代码的问题是您每次都重新生成列表以选择新的路径名。只要您在生成列表的目录中保留相同的文件,这可能会一遍又一遍地为您提供相同的路径名。
对于偶尔运行脚本的情况,简单的答案是将进程文件移走(或删除它们)。这样,下次运行脚本并重新生成随机列表时,已处理的文件将不会成为列表的一部分。
例如,假设所有文件都位于目录中或目录
$HOME/newfiles
下,以下将选择一个文件,然后将其移动到$HOME/oldfiles
:该答案的其余部分与您希望在一次和相同的脚本调用中循环随机路径名的情况有关。
假设您的文件和目录不包含嵌入的换行符,这显示了 Jeff Schaller在评论中建议的内容:
这将为您提供当前目录中或当前目录下的常规文件的随机路径名,如果正如我所提到的,层次结构中的路径名都不包含换行符(在这种情况下
shuf
会打乱这些名称)。一个安全的变体是用一个以 nul 结尾的列表来打乱列表:
此示例(以及下一个示例)改编自https://unix.stackexchange.com/a/543188/116858
在
zsh
外壳中,你可以做这与上面的代码类似,不同之处在于它使用 shell glob 并且没有面向行的文本过滤工具,文件名中的换行符不会成为问题(并且您不必传递以 nul 结尾的列表)。
这样做的好处
zsh
是您不需要调用任何外部工具。如果我正确理解了这个问题,OP 可以做的一件事就是将列表打乱到一个文件中(或变量,如果在
BASH
脚本中),然后从该列表中提取元素。这样,OP 将不会调用同一个文件两次,直到完整列表的末尾。例如,
在文件中创建列表,然后通过以下方式调用它,
或与
sed
or等效的行awk
。或者,如果这一切都被放入
BASH
脚本中,也可以执行以下操作:inode
与...一起工作怎么样?文件是否在您的搜索路径中无关紧要
seen
,如果是,则只需将其自己添加inode
到自身以被筛选掉。对于单个检查会话,只需遍历列表
注意: 假设文件没有被删除。如果它们是和
inode
s 被重用,那么它们将不得不从seen
在发现
sed
复制和重写文件并更改文件之后inode
,seen
这种方法变得更加复杂......删除问题的解决方案可能是使用ed
而不是sed
.删除文件
touch wood
在这里它将跟踪洗牌的文件。
每次使用
find
都需要更多时间...相反,最好在此处使用 mlocate 实用程序...以这种方式
updatedb
仅查找新文件而不是重新扫描所有文件