Take the 2-minute tour ×

I am trying to write a simple script that will iterate through all drives except sda. Right now I have this

for i in $(find /dev/ -name "sd*" ! -name "sda*")
        echo $i

However this includes partitions like /dev/sdb1, whereas I only want the root drive like /dev/sdb.

How do I modify the find statement to guarantee I don't get any of the numbered files?

share|improve this question
Do you really want to exclude sda or is it a wrong example? –  andcoz Sep 20 '11 at 15:57
I do want to exclude sda. When the script is finished, basically all the drives in the machine will have all their data erased. I don't want that to happen to sda, as that's where Linux is installed. –  Phil Sep 20 '11 at 20:28

4 Answers 4

up vote 4 down vote accepted

Don't use command substition in that manner, you'll end up with problems when word splitting is applied. Just do

find /dev/ -regex '/dev/sd[a-z]+' ! -name 'sda'

If your true objective is to show base block devices, just look in /sys/block.

share|improve this answer
After some testing, I've found that this won't pick up drives like /dev/sdaa or /dev/sdab –  Phil Sep 21 '11 at 13:43
@Phil - Good point, fixed. –  Chris Down Sep 21 '11 at 14:11

Supposing you have a single letter after sd, no need to use find.
In bash you can do

shopt -s nullglob
for dev in /dev/sd[!a]; do
    echo "$dev"

The first line is to have no output when no match exist.


To extend to an undetermined number of letters, the glob could be

printf '%s\n' /dev/!(sda|*[0-9])

where !(pattern) means everything but pattern, and excluded patterns are, in the specific case sda and *[0-9] (everything ending in a number).

Extended globs should to be turned on for this to work (i.e. shopt -s extglob).

share|improve this answer
No need to use a for loop, just do shopt -s nullglob ; printf '%s\n' /dev/sd[!a] –  Chris Down Sep 20 '11 at 17:01
@Chris Down: I suppose he want to elaborate more on "$dev", echo "$dev" is just a placeholder. –  enzotib Sep 20 '11 at 17:13
Why not just ls /dev/sd[!a]? –  bahamat Sep 20 '11 at 19:30
Is it possible to do something similar, but supporting more than 26 drives (/dev/sdaa)? –  Phil Sep 20 '11 at 20:41
Do you mean printf '%s\n' /dev/sd!(a|*[0-9])? –  Phil Sep 20 '11 at 22:24

If you want to get list of disk devices on linux I suggest:

paste -s /sys/dev/block/*/uevent | sed -n '/DEVTYPE=disk/s|.*DEVNAME=\(.*\)\t.*|/dev/\1|p'

This will give you also list of potential disks like /dev/loop3 or /dev/ram12.

If you want list of real "partitonable" disks, you can ask fdisk:

LANG="C" fdisk -l | sed -n 's|^Disk \(/.*/.*\):.*|\1|p'

Then you can filter out the sda:

share|improve this answer
I may be a noob, but this looks really complicated and error-prone compared to the alternatives. –  Phil Sep 21 '11 at 13:47
Alternatives will fail on many drives. For example hda hdb and other. Also, some drives (not partitions) has numbers in name (loop5, ram3, ...). My solution is fast and reliable. –  Michał Šrajer Sep 21 '11 at 17:34

assuming you are sure you are dealing with sd*'s and not hd*'s

find /dev/ -name "sd[b-z]"

should do the trick.

share|improve this answer

Your Answer


