Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run bash script to automatically copy contents from USB device after USB device mount

I have a python script to copy all files from a USB storage device to a target folder in my Ubuntu machine. I have never programmed in Python before.

import os
import shutil
from shutil import copytree, ignore_patterns

files = os.listdir('/media/user/HP drive')

destination = '/home/user/Documents/Test/%s'
try :
    for f in files:
        source = '/media/user/HP drive/%s' % f
        copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))    
except Exception as e:
    print(e)

The above script runs fine but it creates a folder %s inside the Test folder with the lock symbol. When I remove the %s and just use

destination = '/home/user/Documents/Test/'

It gives me [Errorno 17] file exists.

This is the bash script(copy.sh) which I want to run when a USB device is mounted.

#!/bin/sh

python /var/www/html/copy_flash.py    #This doesn't work.

# echo "My message" > /var/www/html/thisisaverylongfilename.txt #This works

So the python command is not working but the echo command does when I plug in a USB.

Here's the line I added in /etc/udev/rules.d/test.rules

ACTION=="add",KERNEL=="sdb*", RUN+="/var/www/html/copy.sh"

Is it because the USB drive is not ready when the bash script runs?

  1. How do I copy the USB drive contents in a regular folder and not in %s?
  2. How do I actually copy the contents?
like image 911
DragonBorn Avatar asked Aug 31 '25 10:08

DragonBorn


2 Answers

In order to not use %s you can use the format method.

source = '/media/users/HP/{path}'.format(path=your_filename_here)

You can use any name within the braces which will create the keyword arguments of format. You can also use numbers which are converted to positional arguments. An example:

'Hello {0}! Good {1}'.format('DragonBorn', 'Evening!')

copytree from shutil also requires that the destination not exist. So you will need to check if the destination exists and remove it if it does. You can use os.rmdir and os.path.exists for that. shutil may also have an equivilent function.

https://docs.python.org/3.5/library/shutil.html#shutil.copytree

You can do this check and copy the tree with:

if os.path.exists(destination):
    if os.listdir(): # If the directory is not empty, do not remove.
        continue
    os.rmdir(destination)
shutil.copytree(source, destination)

If you want to remove the entire tree under the directory you can use shutil.rmtree().

if os.path.exists(destination):
    shutil.rmtree(destination)
like image 127
Ethan Henderson Avatar answered Sep 02 '25 22:09

Ethan Henderson


Solution for 1: How do I copy the USB drive contents in a regular folder and not in %s?

I made it to work from Ethan's answer.

Solution for 2: How do I actually copy the contents?

Okay so I found out about systemd from this answer and the advantage it has over udev rule is that the script really fires after mount, not after adding system device which is why my python script was unable to copy the files because the script was running before the device was actually mounted.

I removed the file /etc/udev/rules.d/test.rules

and created a new file in /etc/systemd/system/copy.service with the contents:

[Unit]
Description=My flashdrive script trigger
Requires=media-YourMediaLabel.mount
After=media-YourMediaLabel.mount

[Service]
ExecStart=/home/you/bin/triggerScript.sh

[Install]
WantedBy=media-YourMediaLabel.mount

Run this command sudo systemctl list-units -t mount. Find your device and replace media-YourMediaLabel.mount above with your device unit.

Then you have to start/enable the service:

sudo systemctl start copy.service
sudo systemctl enable copy.service

And that's it. Your USB device's content will be automatically copied in your target destination after it's mounted.

like image 36
DragonBorn Avatar answered Sep 02 '25 23:09

DragonBorn