Я предоставлю метод, который вы просили, а также гораздо более простой метод, если разделы не требуются. Я также буду делать примеры только для ext4, остальное должно быть возможно вывести:
Файл изображения с разделами:
#!/bin/sh
FILE=MyDrive.img
# create new 2Gb image file, will overwrite $FILE if it already exists
dd if=/dev/zero of=$FILE bs=1M count=2048
# make two 1Gb partitions and record the offsets
offset1=$(parted $FILE \
mklabel msdos \
mkpart primary ext2 1 1024 \
unit B \
print | awk '$1 == 1 {gsub("B","",$2); print $2}')
offset2=$(parted $FILE \
mkpart primary ext2 1024 2048 \
unit B \
print | awk '$1 == 2 {gsub("B","",$2); print $2}')
# loop mount the partitions and record the device
loop1=$(losetup -o $offset1 -f $FILE --show)
loop2=$(losetup -o $offset2 -f $FILE --show)
# create and mount the filesystems
mkdir -p /tmp/mnt{1,2}
mkfs.ext4 $loop1
mount $loop1 /tmp/mnt1
mkfs.ext4 $loop2
mount $loop2 /tmp/mnt2
# file write test
touch /tmp/mnt1/file_on_partition_1
touch /tmp/mnt2/file_on_partition_2
# cleanup
umount /tmp/mnt1 /tmp/mnt2
losetup -d $loop1 $loop2
Файл образа без разделов:
#!/bin/sh
FILE=MyDrive.img
# create new 2Gb image file, will overwrite $FILE if it already exists
dd if=/dev/zero of=$FILE bs=1M count=2048
# create and mount filesystem
mkfs.ext4 -F $FILE
mount $FILE /mnt
# file write test
touch /tmp/mnt/file_in_imagefile
# cleanup
umount /mnt
Надеюсь, это не требует пояснений, проще было выразить этот ответ в сценарии оболочки.
Думаю, вы надеетесь, что bash это сделает:
(A && B) || (C && D) || E
но на самом деле это происходит
(A && B || C) && D || E
Где D выполняется, если либо либо B, либо C завершаются успешно.
Добавить больше группировок:
[ -e filename ] && echo filename || {
[ -e../filename ] && echo../filename || {
echo 'ERROR: failed to find "filename"' 1>&2
exit -1
}
}
или
{ [ -e filename ] && echo filename ; } ||
{ [ -e../filename ] && echo../filename; } ||
{ echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
или используйте очень четкий и читаемый стиль if-elif-else
, продемонстрированный @Jesse _b.
Шаг -за шагом -, это происходит:
имя файла находится в текущем каталоге:
[ -e filename ] \ # test succeeds, status is now 0
&& # status is zero, will execute this branch
echo filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
[ -e../filename ] \ # not executed
&& # status is zero, will execute this branch
echo../filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
{ echo; exit; } # not executed
имя файла находится в родительском каталоге:
[ -e filename ] \ # test fails, status is now 1
&& # status is non-zero, do not execute this branch
echo filename \ # not executed
|| # status is non-zero, will execute this branch
[ -e../filename ] \ # test succeeds, status is now 0
&& # status is zero, will execute this branch
echo../filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
{ echo; exit; } # not executed
&&
и ||
имеют одинаковый приоритет, поэтому:
Когда команда проходит, она ищет следующую &&
и выполняет ее, даже если это не непосредственно смежный оператор. Вы должны никогда не использовать более одного из этих операторов в одном списке команд. Если требуется более одного, вы используете конструкцию if/then.
$ true && true || echo yes && echo no
no
Это сильно отличается от:
if true; then
true
else
echo yes && echo no
fi
$ if true; then true; else echo yes && echo no; fi
$
Или:
$ true && false || echo yes && echo no
yes
no
$ if true; then false; else echo yes && echo no; fi
$
Я бы написал вашу конструкцию как:
if [ -e filename ]; then
echo filename
elif [ -e../filename ]; then
echo../filename
else
echo 'ERROR: failed to find "filename"' >&2
exit -1
fi