Como detectar e escrever automaticamente em usb com espaços variáveis em seu nome

1

Estou fazendo o segundo exercício BASH do Guia de script do bash do TLDP , e tenho a maior parte do ele descobriu até a parte quando chega a hora de copiar os arquivos compactados para um USB inserido.

Home Directory Listing

Perform a recursive directory listing on the user's home directory and save the information to a file. Compress the file, have the script prompt the user to insert a USB flash drive, then press ENTER. Finally, save the file to the flash drive after making certain the flash drive has properly mounted by parsing the output of df. Note that the flash drive must be unmounted before it is removed.

À medida que eu progrida com o roteiro, está se tornando menos ... elegante, e fiquei me perguntando se havia uma maneira melhor de fazer isso. Eu sei que a criação de arquivos provavelmente não é a maneira mais eficiente de fazer comparações, mas ainda não tenho as expansões de shell imaginadas, e pretendo alterá-las uma vez que eu funcione.

O problema é especificamente, para garantir que o usb esteja montado e que eu esteja escrevendo para o USB e em nenhum outro lugar. Estou comparando a última linha de df depois que o USB é conectado com a última linha de df do diff entre df antes do USB ser conectado e df após o USB ser conectado e do looping até que eles combinem. Infelizmente, o resultado diff começa com um & gt ;, mas pretendo usar sed para me livrar disso. O problema real é o caminho para onde o meu usb é montado é:

/media/flerb/"Title of USB with spaces"

Para tornar este portátil para USBs que pode ter nomes diferentes, é a minha melhor aposta para fazer algo com o awk e os separadores de campo? E como acompanhamento, eu sei que isso é muito deselegante, e me pergunto se há uma maneira mais clara de fazer isso ... especialmente porque este é o segundo exercício e ainda em FÁCIL.

A saída das caudas do df é:

/dev/sdb1                     15611904  8120352   7491552  53% /media/flerb/CENTOS 7 X8
> /dev/sdb1                     15611904  8120352   7491552  53% /media/flerb/CENTOS 7 X8

O script até agora

 1 #!/bin/bash
  2 
  3 if [ "$UID" -eq 0 ] ; then
  4         echo "Don't run this as root"
  5         exit 1
  6 fi
  7 
  8 #Create a backup file with the date as title in a backup directory
  9 BACKUP_DIR="$HOME/backup"
 10 DATE_OF_COPY=$(date --rfc-3339=date)
 11 BACKUP_FILE="$BACKUP_DIR/$DATE_OF_COPY"
 12 
 13 [ -d "$BACKUP_DIR" ] || mkdir -m 700 "$BACKUP_DIR"
 14 
 15 #find all files recursively in $HOME directory
 16 find -P $HOME >> "$BACKUP_FILE"
 17 
 18 #use lzma to compress
 19 xz -zk --format=auto --check=sha256 --threads=0 "$BACKUP_FILE"
 20 
 21 #making files to use in operations
 22 BEFORE="$BACKUP_DIR"/before_usb.txt
 23 AFTER="$BACKUP_DIR"/after_usb.txt
 24 DIFFERENCE="$BACKUP_DIR"/difference.txt
 25 
 26 df > "$BEFORE"
 27 read -p 'Enter USB and press any button' ok
 28 sleep 2
 29 df > "$AFTER"
 30 diff "$BEFORE" "$AFTER" > "$DIFFERENCE"
 31 sleep 2
 32 echo
 33 
 34 TAIL_AFTER=$(tail -n 1 "$AFTER")
 35 TAIL_DIFF=$(tail -n 1 "$DIFFERENCE")
 36 
 37 until [ "$TAIL_AFTER" == "$TAIL_DIFF" ] ;
 38 do
 39         echo "Not yet"
 40         df > "$AFTER"
 41         TAIL_AFTER=$(tail -n 1 "$AFTER")
 42         diff "$BEFORE" "$AFTER" > "$DIFFERENCE"
 43         TAIL_DIFF=$(tail -n 1 "$DIFFERENCE")
 44         echo "$TAIL_AFTER"
 45         echo "$TAIL_DIFF"
 46         sleep 1
 47 
 48 done
 49 exit $?
    
por trogdor 12.07.2017 / 19:28

1 resposta

0

Para obter o USB correto e seu caminho:

  • notou que o primeiro USB conectado ao meu sistema está montado no sistema de arquivos / dev / sdb1 e o segundo está montado no sistema de arquivos / dev / sdc1. Eu adicionei uma seção para alternar para / dev / sdc1 se udevadm info -q all -n "/dev/sdb" | grep "ID_BUS=usb" retornou true.

  • se diff entre df --output=target | grep "/media/darren" antes e depois tiver "/ media / darren", provavelmente o novo USB. USB está montado.

  • if udevadm info -q all -n "/dev/sdb" | grep "ID_BUS=usb é verdadeiro, então o dispositivo montado em "/ dev / sdb" é um dispositivo usb

  • para obter o caminho e ter certeza de que estava pegando o caminho certo: df --output=source,avail,target | grep "$FILESYSTEM" | grep "$MOUNTPOINT" e algum awk realmente legal

    udevadm info -q all -n "$FILESYSTEM" | grep "ID_BUS=usb" > $RESULT
    USB_ADDR="$BACKUP_DIR"/usb_addr.txt
    if grep "ID_BUS=usb" "$RESULT" ; then
        df --output=source,avail,target | grep "$FILESYSTEM" | grep "$MOUNTPOINT" > "$USB_ADDR"
        awk -i inplace '{$0=gensub(/\s*\S+/,"",1)}1' "$USB_ADDR"
        awk -i inplace '{$0=gensub(/\s*\S+/,"",1)}1' "$USB_ADDR"
        sed -i 's/^ *//' "$USB_ADDR"
    

Infelizmente, a difusão falha se outras coisas forem adicionadas ou removidas. Mas, pelo menos, falha muito se ele pega o dispositivo errado ao usar a saída df filtrada e o grepping para o sistema de arquivos e o ponto de montagem.

Tentei awk 'NR!=1{print $NF}' <(df)|sort . Ainda não é ótimo em expansões bash.

#!/bin/bash

if [ "$UID" -eq 0 ] ; then
        echo "Don't run this as root"
        exit 50
fi

#Create a backup file with the date as title in a backup directory
BACKUP_DIR="$HOME/backup"
DATE_OF_COPY=$(date --rfc-3339=date)
BACKUP_FILE="$BACKUP_DIR/$DATE_OF_COPY"

[ -d "$BACKUP_DIR" ] || mkdir -m 700 "$BACKUP_DIR"

#find all files recursively in $HOME directory
find -P $HOME >> "$BACKUP_FILE"

#use lzma to compress
xz -zk --format=auto --check=sha256 --threads=0 "$BACKUP_FILE"

#making files to use in operations of before and after usb is inserted info and diff between them
#this is part of how we will insure that we are writing to the correct device
BEFORE="$BACKUP_DIR"/before_usb.txt
AFTER="$BACKUP_DIR"/after_usb.txt
DIFFERENCE="$BACKUP_DIR"/difference.txt
#MOUNTPOINT=where computer mounts USBs by default
MOUNTPOINT="/media/darren"
FILESYSTEM="/dev/sdb"
RESULT="$BACKUP_DIR"/result.txt


#if there is something on the mountpoint before we plug in the usb, we want to know
#so the new device is written to
udevadm info -q all -n "$FILESYSTEM" | grep "ID_BUS=usb" > $RESULT
if grep "ID_BUS=usb" "$RESULT" ; then
        FILESYSTEM="/dev/sdc"
        echo $FILESYSTEM
fi        

df --output=target | grep $MOUNTPOINT > "$BEFORE"

read -p 'Enter USB or hard drive and press any button' ok

df --output=target | grep $MOUNTPOINT > "$AFTER"
#dif them to find the new one
diff "$BEFORE" "$AFTER" > "$DIFFERENCE"

# Look in mountpoint in the difference between the before and after df outputs
SEARCH_FOR_MOUNT=$(grep "$MOUNTPOINT" "$DIFFERENCE")

until [ "$SEARCH_FOR_MOUNT" ] ;
do
        df --output=target | grep $MOUNTPOINT > "$AFTER"
        diff "$BEFORE" "$AFTER" > "$DIFFERENCE"
        SEARCH_FOR_MOUNT=$(grep "$MOUNTPOINT" "$DIFFERENCE")

done
#check if new device plugged into filesystem is a USB
udevadm info -q all -n "$FILESYSTEM" | grep "ID_BUS=usb" > $RESULT
USB_ADDR="$BACKUP_DIR"/usb_addr.txt
if grep "ID_BUS=usb" "$RESULT" ; then
        df --output=source,avail,target | grep "$FILESYSTEM" | grep "$MOUNTPOINT" > "$USB_ADDR"
        awk -i inplace '{$0=gensub(/\s*\S+/,"",1)}1' "$USB_ADDR"
        awk -i inplace '{$0=gensub(/\s*\S+/,"",1)}1' "$USB_ADDR"
        sed -i 's/^ *//' "$USB_ADDR"

        if [ ! -s $USB_ADDR ] ; then
              echo "Error finding USB Address"
              exit 100


        ADDR=$(cat "$USB_ADDR")
        cp "$BACKUP_FILE.xz" "$ADDR"
        rm "$BACKUP_FILE" "$USB_ADDR" "$RESULT" "$BEFORE" "$AFTER" "$DIFFERENCE"

else
        echo "Device is not a USB"
        exit 52
fi

exit $?
    
por 13.07.2017 / 03:41