我想移动目录中当前未使用的文件。我觉得lsof
、find
和的某种组合xargs
可以起作用,但我做不到。到目前为止,我创建了以下命令:
lsof mydir/*|awk '(NR>1){print $9}
这给了我一个正在使用的文件列表。如果我能得到一个没有被使用的文件列表,那么像 xargs 这样的命令就可以mv
对这些文件发出一个。我似乎找不到一个优雅的方式来做到这一点。有人能给我一些提示吗?
答案1
我会这么做。
find $dir -maxdepth 1 | sort > $other_dir/all_files
lsof $dir/* | awk '(NR>1) {print $9}' | sort > $other_dir/in_use_files
comm -2 -3 $other_dir/all_files $other_dir/in_use_files
来自 comm(1):
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
现在只需将其重新格式化为一系列mv
语句即可。可能像这样:
while IFS= read file ; do
mv "$file" "$destination/"
done < <(comm -2 -3 all_files in_use_files)
或者如果您愿意,可以使用另一个中间文件。
答案2
也许这不是最好的方法,但只需几分钟就可以编写代码:
获取打开的文件列表(如果尚未排序则进行排序)
获取所有文件的列表(如果尚未排序则进行排序)
比较两个列表
xargs 无论如何
这里的步骤数将使本来应该引起关注的事情变得明显,即竞争条件——您选择它们时正在使用的文件可能不是您实际移动它们时正在使用的文件。
答案3
感谢@Sorpigal 的建议,我找到了一种无需循环即可完成此工作的简单方法:
comm -2 -3 <(find $dir -maxdepth 1 -type f|sort) <(sudo lsof $dir/* | awk '(NR>1) {print $9}'|sort) | xargs -I {} mv {} $move_dir
我不确定竞争条件,但对我而言这并不重要。文件打开一次进行写入,然后应关闭,直到移动为止。
答案4
这就是定影器的用途。
/var/log/apache2
$ fuser access.log
/var/log/apache2/access.log: 2132 15456 16414 19555 19622
/var/log/apache2
$ fuser access.log 2>/dev/null
2132 15456 16414 19555 19622
/var/log/apache2
$ if [ ! -z "$(fuser access.log 2>/dev/null)" ]
> then
> echo "this file is in use"
> else
> echo "this file is not in use"
> fi
this file is in use