1

Я хочу переместить файлы в каталог, который в данный момент не используется. У меня есть ощущение, что какая-то комбинация lsof , find и xargs может сработать, но я не совсем могу туда добраться. Пока что я создал следующую команду:

lsof mydir/*|awk '(NR>1){print $9}

Это дает мне список файлов, которые используются. Если бы я мог просто получить список файлов, которые НЕ используются, то что-то вроде xargs могло бы создать mv для этих файлов. Я просто не могу найти элегантный способ сделать это. У кого-нибудь есть намеки на меня?

4 ответа4

3

Я бы сделал это так

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

Из комм (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

Это то, для чего предназначен термоэлемент.

/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
2

Возможно, не самый лучший способ, но можно просто закодировать его за несколько минут:

получить список открытых файлов (сортировка, если еще не)

получить список всех файлов (сортировать, если еще нет)

различать два списка

XARGS все

Количество шагов здесь сделает очевидным то, что в любом случае должно вызывать беспокойство, а именно гоночные условия - файлы, которые используются при их выборе, могут не быть файлами, которые используются, когда вы на самом деле их перемещаете.

2

Благодаря предложению @ 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

Я не уверен в условиях гонки, но в моем случае это не имеет значения. Файлы открываются один раз для записи, а затем должны быть закрыты до перемещения.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .