I want to modify the script text below, to change the file permissions, owner and move it, only if the file is not open by another process.

cd /mnt/usbdrive/DVR
sudo chown 777 -R /mnt/usbdrive
sudo chmod 777 -R /mnt/usbdrive
find .  -mindepth 2 -type f -name '*.ts' -exec mv -t /mnt/usbdrive {} +
  • which operating system are you using ? Linux has the fuser command for that, usually packaged in "psmisc" – LL3 Apr 16 at 17:28
  • Ubuntu 18. I attempted to use fuser but couldn't sort out how to format the conditional statement. – Houston User Apr 17 at 3:02

A simple and lean find command for your case could be:

find .  -mindepth 2 -type f -name '*.ts' -exec fuser -s {} \; -a -exec mv /mnt/usbdrive {} \;

Here we take advantage of find’s expression abilities: note the -a operator (meaning “and”) so that mv gets executed only if fuser exits with 0, meaning that the file is open.

This is the safest command, capable of dealing with any character possibly present in your files's names.

But this command can also be very slow if you have many files in that directory. In fact you had used the {} + syntax along mv’s -t option to ease that burden.

Unfortunately we cannot just use that syntax for the two -exec actions, because fuser would exit with 0 when any one of the indicated files are open, and we wouldn’t even know which files are, among those provided as its arguments by find.

We can still use the {} + syntax here too, but we need a more complicated command. One like this:

find . -mindepth 2 -type f -name '*.ts' -exec fuser {} + 2>&1 | sed 's/^\(.\+\):.*/\1/' | xargs mv -t /mnt/usbdrive

Breaking down what’s being -executed by find, we basically have fuser consider all files in one run but also filter its output through sed to get only the file names (fuser outputs PIDs along with file names) to finally pipe them to an xargs running your original mv command in one go. For testing I would recommend adding the -p option to such xargs to see what would be moved if confirmed.

Then, I also notice you say you’d like to change permissions and owner besides moving the file only if it is not open, but then I see you do a chown plus chmod to whole directory beforehand. (As a side note, chown 777 does not make sense at all, you want to put a username there.. unless 777 is indeed a user-id in your system, but I doubt it).

So if you’d rather wish to do as you said, you might add those commands to the xargs by packing them in a shell’s compound command.

Like this:

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 "${@}"' --

This actually only shows the commands that would be run. I would recommend to experiment with it, and when you’re ready to really apply it just remove the echos.

Important note: these latter two commands allowing the use of find's {} + syntax cannot deal with file names having embedded newlines because of the filtering done by sed. Dealing with those is possible but would get even more complex because of fuser’s particular output. I think it’s reasonable to assume your file names do not have newlines embedded, otherwise you might rather use the first simpler though slower command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.