Простая и компактная find
команда для вашего случая может быть:
find. -mindepth 2 -type f -name '*.ts' -exec fuser -s {} \; -a -exec mv /mnt/usbdrive {} \;
Здесь мы воспользовались возможностями выражения find
:обратите внимание на оператор -a
(, означающий «и» ), так что mv
выполняется, только если fuser
завершается с 0, значит файл открыт.
Это самая безопасная команда, способная работать с любыми символами, которые могут присутствовать в именах ваших файлов.
Но эта команда также может быть очень медленной, если в этом каталоге много файлов. На самом деле вы использовали синтаксис {} +
вместе с опцией mv
-t
, чтобы облегчить это бремя.
К сожалению, мы не можем просто использовать этот синтаксис для двух -exec
действий, потому что fuser
выйдет с 0, когда любой из указанных файлов открыт, и мы даже не будем знать, какой файлы входят в число тех, которые предоставляются в качестве аргументов find
.
Мы по-прежнему можем использовать синтаксис {} +
и здесь, но нам нужна более сложная команда. Вот такой:
find. -mindepth 2 -type f -name '*.ts' -exec fuser {} + 2>&1 | sed 's/^\(.\+\):.*/\1/' | xargs mv -t /mnt/usbdrive
Разбивая то, что -exec
использует find
, мы в основном имеем fuser
рассмотрение всех файлов за один запуск, но также фильтруем его вывод через sed, чтобы получить только имена файлов(fuser
выводит PID вместе с именами файлов ), чтобы, наконец, направить их в xargs
, выполняющую исходную команду mv
за один раз. Для тестирования я бы рекомендовал добавить опцию -p
к такому xargs
, чтобы увидеть, что будет перемещено в случае подтверждения.
Затем я также заметил, что вы говорите, что хотели бы изменить разрешения и владельца помимо перемещения файла, только если он не открыт, но затем я вижу, что вы выполняете chown
плюс chmod
на весь каталог заранее. (В качестве примечания, chown 777
вообще не имеет смысла, вы хотите поместить туда имя пользователя.. если только 777 действительно не является идентификатором пользователя -в вашей системе, но я сомневаюсь в этом ).
Итак, если вы хотите сделать то, что вы сказали, вы можете добавить эти команды в xargs
, упаковав их в составную команду оболочки.
Вот так:
find. -mindepth 2 -type f -name '*.ts' -exec fuser {} + 2>&1 | sed -e 's/^\(.\+\):.*/\1/' | xargs sh -c 'echo sudo chmod 777 "${@}"; echo sudo chown user "${@}"; echo mv -t /mnt/usbdrive "${@}"' --
Это на самом деле только показывает команды, которые будут выполняться. Я бы порекомендовал поэкспериментировать с ним, и когда вы будете готовы действительно применить его, просто удалите echo
s.
Важное примечание:эти две последние команды, позволяющие использовать синтаксис find
's {} +
, не могут работать с именами файлов, содержащими встроенные символы новой строки из-за фильтрации, выполняемой sed
. Работа с ними возможна, но будет еще сложнее из-за особого вывода fuser
. Я думаю, разумно предположить, что ваши имена файлов не имеют встроенных символов новой строки, иначе вы можете использовать первую, более простую, но более медленную команду.
Все команды, которые вы вводите одну за другой в приглашении, можно просто поместить в файл сценария и выполнить один раз.
Единственным требованием является строка интерпретатора, которая должна быть в начале файла
#!/bin/sh
вы можете написать скрипт для других, таких как bash(#!/bin/bash
)или zsh(#!/bin/zsh
)
Сделайте ваш скрипт исполняемым, запустивchmod +x scriptFile.sh
(расширение sh хорошо иметь, так как оно указывает, что это файл скрипта)
Запустите скрипт, нажав
./scriptFile.sh
Дополнительно :Вы можете добавить путь к каталогу в переменную PATH, чтобы иметь возможность выполнять скрипт из любого каталога, просто вызвав scriptFile.sh
так же, как вы вызываете любую другую команду оболочки ls
илиcat
Скрипты сохраняются в текстовые файлы. Вы можете создать его в текстовом редакторе,например gedit
илиnano
:
$ nano yourscript.sh
Имя файла вообще и расширение имени файла в частности не имеют значения . В вашем файле скрипта вы должны объявить исполняемый файл интерпретатора для его запуска (как shebang). Затем добавьте свой код. Чтобы сохранить сценарий в nano
, нажмите Ctrl + X , затем введите y
и нажмите Enter .
Если вы передаете скрипту аргументы, вы можете ссылаться на них в своем коде по номеру (первый переданный аргумент — $1
, второй — $2
и так далее ). $0
— это имя самого скрипта.
Как правило, переменные всегда заключаются в двойные кавычки .
Взяв ваш код, например, скрипт может быть:
#! /bin/bash
curl -O "$1"
head -n 12 cities.csv
После#!
может быть пробел, но это не обязательно. В большинстве случаев вы можете проверить переменную $0
в терминале для исполняемого файла оболочки , интерпретирующего ваши команды в терминале :
$ echo $0
/bin/bash
Предполагая, что вам нужны только первые 12 строк загруженного файла, вы можете пропустить сохранение загруженного файла на диск и передать его следующей команде:
#! /bin/bash
curl -s "$1" | head -n 12
В качестве бонуса он позволяет вам не указывать имя файла в сценарии.
Предполагая, что вы сохранили свой скрипт как yourscript.sh
, сначала добавьте разрешение на его выполнение:
$ chmod +x yourscript.sh
Затем для его запуска нужно указать путь к нему и предоставить аргументы. Если он находится в текущем каталоге, вы можете указать путь к нему, добавив перед ним ./
, например:
$./yourscript.sh 'https://people.sc.fsu.edu/~jburkardt/data/csv/cities.csv'