Basically what's happening:

  • I plug in my Pico W to my Raspberry Pi 4B (8GB model, running Ubuntu Server 23.10 arm64) via USB while holding down the button, so it's in BOOTSEL mode.
  • I run sudo dmesg on the Pi 4B to see that there's a new mass storage device attached, i.e. the Pico's flash partition.
  • I manually mount the drive with sudo mount /dev/sdb1 /mnt/pico
  • I copy a UF2 "hello world" binary onto the Pico, runs as expected
  • I unplug the Pico and get back to work on programming.
  • I plug the Pico back in to install a new binary on it.

The issue happens in the last step. When I run sudo dmesg again to see the name of the new mass storage device, it "shifts up" by one letter, like if it was sdb last time, the next time it'll be sdc. This seemingly goes on forever, but I haven't hit Z yet. Furthermore, the letters 'reset' when I reboot the Pi 4B, so it's back to sdb on the first time I plug the Pico in after a reboot. (I have a proper HDD attached on sda.)

How can I get my Pi 4B to reuse the same logical mass storage device for every time I plug my Pico back in BOOTSEL mode?

  • "How can I get my Pi 4B to reuse the same logical mass storage device for every time I plug my Pico back in BOOTSEL mode" reboot before plugging it in.
    – Milliways
    Jan 27 at 7:02

2 Answers 2


Assignment of the device names (sda, sdb, etc) is a function of the Linux kernel. If that's not bad enough, since systemd horned in on the action, what you're trying to do will involve following systemd guidance as well.

This is a completely un-tested idea:

  1. cobble together a script that reads the latest device name of your Pico (you could use lsblk as a source for the device name)

  2. add logic to the script that will create a symbolic link from whatever the latest device name is to something like pico; i.e.:

KERNEL=="<the currently-assigned device name from step 1>", SYMLINK+="pico" 
  1. Install the script in /etc/udev/rules.d/ using a filename like 20-devsymlink.rules.

This should be trivial for someone who's labeled himself as HackerDaGreat.

  • I'll try this out when I get time. Btw, I came up with the username when I was a silly 11-year-old; we've all been there! Dec 26, 2023 at 22:54
  • I didn't try your solution exactly, but I used the first part about getting a new device's name as the base for my own script. See the answer I posted on this question. *P.S. I can't for the life of me figure out why I can't directly ping you. The ping thingy seems to be broken for me on this website. Dec 28, 2023 at 5:19
  • Oh - the ping thing is because you're posting under my thread/answer... that means I always get a notice. You OTOH are one of potentially several commenters, so I use your handle to ensure you get notification. WRT your solution: Good For You! If it works, you should accept it as the answer (may have to wait a day or two??); that helps others, but you get no points for it :(
    – Seamus
    Dec 28, 2023 at 5:42

So I didn't end up getting the whole "reuse the same device name" thing working, but I DID end up making a solution that fit my exact use case.

Basically what this script does, is it essentially gets the logical device name of the Pico through some semi-"hacky" means which involve a few assumptions[1] about your environment (I used Ubuntu Server 23.10). Then it mounts that device to a directory of your choice. After that, it copies a UF2 binary of your choice to the mount point, which triggers execution of the new binary on the Pico, which is what I was looking for.


# deploy.sh: write a UF2 binary to a Raspberry Pi Pico (W) in BOOTSEL mode
# Probably needs root to work properly! (mount and cp commands)

mount_location=/mnt/pico # where the flash partition shall be mounted
                         # (no trailing slash, please)
binary=a0_bl.uf2 # the UF2 binary to send to the Pico

before=$(lsblk -o NAME) # get existing devices
read -n 1 -s -r -p "Plug the Pico in BOOTSEL mode. Press Enter when finished."
echo # runs when Enter is pressed
after=$(lsblk -o NAME) # get new device list

diff=$(diff <(printf "$before") <(printf "$after")) # find new/changed device
                                                    # (presumed to be the Pico)
dev_name=$(printf "$diff" | grep '^> └─' | cut -c 9-) # get name of the Pico

mount /dev/${dev_name} ${mount_location} # mount the Pico's flash partition
cp $binary ${mount_location} # copy over the UF2 binary

printf "\nDeployed.\n" # It works on my machine™, so no error handling

Thanks @Seamus for parts of the basic idea.

[1]: The only "assumptions" made about the environment are:

  • Devices are accessible under the directory /dev;
  • You have Bash installed to /bin/bash;
  • The script is run with root permissions (primarily due to use of the mount command);
  • And that lsblk -o NAME prepends > └─ before partition names.

P.S. for anyone wondering, once you hit sdz in device names, the next device will be named sdaa.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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