我正在做第二个 BASH 练习TLDP Bash 脚本指南,直到将压缩文件复制到插入的 USB 部分之前,我已经弄清楚了大部分内容。
主目录列表
对用户的主目录执行递归目录列表并将信息保存到文件中。压缩文件,让脚本提示用户插入 USB 闪存驱动器,然后按 ENTER。最后,通过解析 df 的输出确定闪存驱动器已正确安装后,将文件保存到闪存驱动器。请注意,在移除闪存驱动器之前必须先将其卸载。
随着我编写脚本的进展,它变得越来越不优雅,并且想知道是否有更好的方法来做到这一点。我知道创建文件可能不是进行比较的最有效方法,但尚未计算出 shell 扩展,并打算在其工作后对其进行更改。
具体问题是,确保 USB 已安装并且我正在写入 USB 而不是其他地方。我df
将 USB 插入后的最后一行与USB 插入之前和USB插入后之间的最后一行进行比较,并循环直到它们df
匹配。不幸的是,结果以 > 开头,但我打算使用 sed 来摆脱它。真正的问题是我的USB安装路径是:diff
df
df
diff
/media/flerb/"带有空格的 USB 标题"
为了使这个可移植的 USB 可能有不同的名称,我最好的选择是用 awk 和字段分隔符做一些事情?作为后续,我知道这非常不优雅,并且想知道是否有更干净的方法来解决这个问题......特别是因为这是第二个练习并且仍然是简单的。
df tails 的输出是:
/dev/sdb1 15611904 8120352 7491552 53% /media/flerb/CENTOS 7 X8
> /dev/sdb1 15611904 8120352 7491552 53% /media/flerb/CENTOS 7 X8
到目前为止的脚本
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 $?
答案1
要获取正确的 USB 及其路径:
请注意,插入我系统的第一个 USB 挂载在 /dev/sdb1 文件系统上,第二个 USB 挂载在 /dev/sdc1 文件系统上。我添加了一个部分,如果
udevadm info -q all -n "/dev/sdb" | grep "ID_BUS=usb"
返回 true,则切换到 /dev/sdc1 。如果前后
diff
之间有“/media/darren”,则可能是新的 USB。df --output=target | grep "/media/darren"
USB 已安装。if udevadm info -q all -n "/dev/sdb" | grep "ID_BUS=usb
为 true 则安装在“/dev/sdb”上的设备是 USB 设备找到路径,并确保我抓住了正确的路径:
df --output=source,avail,target | grep "$FILESYSTEM" | grep "$MOUNTPOINT"
并且一些非常好的 awkudevadm 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"
不幸的是,如果添加或删除其他内容,比较就会失败。但是,如果在使用df
过滤的输出并对文件系统和挂载点进行 grep时获取错误的设备,那么至少它会失败。
试过了awk 'NR!=1{print $NF}' <(df)|sort
。 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 $?