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?

  • 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

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.

  • 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).

  • 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
  • 1
    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:

LANG="C" fdisk -l | sed -n 's|^Disk \(/.*/.*\):.*|\1|p' | grep -v sda
  • 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.