首页 > 解决方案 > 移动未使用的文件并保留目录结构

问题描述

我正在尝试从不断写入(文件和文件夹)的源文件夹中移动文件。一旦一个文件不再被写入,它就不会再次被读写。我想将未使用的文件移动到另一个文件夹,但保留目录结构。我最终希望将它添加到一个连续循环中,或者让它定期运行以“清理”源文件夹。

这是我之前和之后的示例:

Before:
Parent/
├── Source/
│   ├── DirA/
│   │   ├── File1InUse.abc
│   │   ├── File2NotInUse.abc
│   │   └── File3InUse.abc
│   └── DirB/
│       ├── File4InUse.abc
│       ├── File5NotInUse.abc
│       └── File6NotInUse.abc
│
├── Destination/

After:
Parent/
├── Source/
│   ├── DirA/
│   │   ├── File1InUse.abc
│   │   └── File3InUse.abc
│   └── DirB/
│       └── File4InUse.abc
│
├── Destination/
    ├── DirA/   
    │   └── File2NotInUse.abc
    └── DirB/
        ├── File5NotInUse.abc
        └── File6NotInUse.abc

我找到了移动未使用文件的移动文件的答案:

comm -2 -3 <(find $dir -maxdepth 1 -type f|sort) <(sudo lsof $dir/* | awk '(NR>1) {print $9}'|sort) | xargs -I {} mv {} $move_dir

我还找到了移动文件和保留目录结构的答案:

也许与rsync

rsync -axuv --delete-after --progress Source/ Target/

我对命令行不是很了解,所以我不确定如何将这两个概念放在一起。

谢谢你的帮助。

标签: linuxbashshellrsync

解决方案


我将这样做。创建一个脚本,以便您可以从其他程序或 cron 作业中使用它。

#! /bin/bash

isUsed() {
    test -w "$1" && echo 1 || echo 0
}

parent_dir=$1
src_dir=$2
dst_dir=$3

while read -r line
do
    retval=$(isUsed "$line")
    if [ $retval -eq "0" ]
    then
        filepath=$(dirname $line)
        filepath=${filepath#$parent_dir}
        filepath=${filepath#$src_dir}
        mkdir -p "$parent_dir$dst_dir$filepath"
        mv "$line" "$parent_dir$dst_dir$filepath"/
    fi
done <<< $(find "$parent_dir$src_dir")

用法

./script.sh Parent/ Source/ Destination/

在职的

  1. isUsed函数用于检查文件当前是否正在使用。

    返回值:1- 正在使用文件,0- 未使用文件

    目前,文件权限用于查找文件是否正在使用中。如果一个文件有写权限,那么它被认为是被使用的。您可以将其更改为任何其他逻辑来评估是否使用了文件,就像lsof您的问题中提到的那样。

  2. find "$parent_dir$src_dir"将列出给定路径中的所有文件和目录。使用 while 循环find一次读取一个命令的输出。$line

    示例:假设$line等于Parent/Source/DirA/File2NotInUse.abc

  3. 我们调用该isUsed函数来检查文件是否正在使用。函数调用的返回值存入$retval

  4. 如果$retval等于"0",则表示该文件未被使用,我们必须将其移动到目标目录。

  5. 首先,我们将使用生成要移动的文件的路径dirname。它将返回文件的相对路径。

    $filepath等于Parent/Source/DirA

    然后我们从filepath.

    因此$filepath成为Source/DirA

    然后我们从filepath.

    因此$filepath现在等于DirA。这filepath将是文件相对于源目录的路径。

  6. 使用Destination/给定的filepath. mkdir -p将创建所有中间目录,如filepath.

    mkdir -p Parent/Destination/DirA

  7. 最后一步是将实际文件从其Source路径移动到新创建的Destination路径。

    mv Parent/Source/DirA/File2NotInUse.abc Parent/Destination/DirA/


推荐阅读