Disclaimer: As the title implies, this is about shell scripting on your Steam Deck. The guide won't teach you how to do that part, it assumes you already have ideas in mind about what scripts you'd want to write. Stopping the usage of Syncthing was what I wanted to do with it, but you can do whatever you like.
Background (you can skip this part)
If you're an avid gamer who picked up a Steam Deck and now you're splitting your time between it and a more traditional gaming computer (or in my case, several other gaming systems as well), you may come across a situation where at some point you want to start doing more advanced things on your Steam Deck - which may mean "how do I get files onto or off of this thing".
When you start searching the web for answers here, the top result you'll get time and time again for Steam deck is "Set up Syncthing".
And to be honest - it's not bad advice. It does what you want: Sets up a way to get files on and off the device. I'd even go so far to say as it's a good way to get started with getting things onto your Deck and maybe keep it around afterwards even if you stop generally using it.
But in a naive install (installing the flatpak of it), most people are only going to figure out how to run it while in Desktop mode.
There are solutions out there where you can configure it to run even in Gaming mode - but the Steam Deck, while powerful, I have concerns about running additional services in the background all the time when really my whole goal is just trying to play games on it. I really only need sync before or after gaming, not during.
Additionally, Syncthing has made decisions about how to resolve conflicts on files which I don't even necessarily want.
Case in point: I enjoy playing the game Graveyard Keeper which, as of the time of writing this, does not currently keep a unified cloud save between running it on Steam Deck and running it on a computer. Even though the files are the same format, name, and contents between platforms, the cloud save includes portions of the host path for the OS they're running on which means it accidentally keeps saves split across different OSes.
After I'm done playing the game on a particular OS, I want the saves on that OS to become the "authoritative" ones and overwrite anything I'd previously had at all, including deleting files that aren't in the current save set. This means sometimes I want "the save that's not on this machine" to completely overwrite the current save - but other times I'm done gaming and want the directionality to flow the opposite way "this is now the latest save, overwrite anything else".
So I need some control and flexibility here.
And the same goes for what Syncthing is actually syncing. Yes, you can add an arbitrary folder to sync - but what if you need some file name translations to happen as a result of that, or the folder you're syncing is a different name on source and destination, etc.
And what if I don't want to sync everything Syncthing is monitoring - just the game or whatever I'm doing and care about right now.
In short: I just want full control of all the things - the opportunity to customize to whatever extent that I like.
If you're familiar with macOS, Linux, and Unix-like OSes at all - chances are you've had exposure to rsync and it probably automatically pops up in your mind in the "I'd like to copy files from A to B" category.
Well good news! Your Steam Deck is a Linux distro and it has rsync already. No need to install a flatpak, just start writing up a shell script and sync away whatever you like wherever you like.
And if one of the things you're trying to sync things to/from is Windows, which doesn't have rsync? You can get a pre-built copy using MSYS2. Run their installer, which will then offer at the end to run the MSYS2 console, where you can type pacman -S rsync
. With the default config, this will install to C:\msys64\user\bin\rsync.exe
. You can use that path from any .bat file, you don't need to run things from the MSYS2 console, just translate your Windows paths to Linux style pathing in any arguments you pass to it (Example: C:\Users\username\foo
becomes /c/Users/username/foo
)
In my case, I also have a Synology in my house which offers the ability to run rsync in daemon mode as an always-on service. Perfect target. Syncthing solves a problem in that it's a multi-client capable sync without needing a central authoritative source, but in my case that's exactly what I'm desiring (and have available).
So how do we make these scripts easy to run?
You can drop a shell script you write anywhere in your home directory and it will generally survive a SteamOS update, but running a shell script after you've written it can be tiresome given the limitations of the on-screen keyboard. systemd offers a lot of capability for automatic running, but if you want to manually trigger any script you develop on your Deck, I'd recommend starting with a .desktop
file - which would allow you to pin it to a tray or leave an icon on your desktop that you can simply tap / click to launch.
An example of such a file could look like this:
#!/usr/bin/env xdg-open
[Desktop Entry]
Name=Name You Want To See
Comment=Whatever You Like Here
Exec=/home/deck/path/to/your/script.sh
Type=Application
Encoding=UTF-8
Terminal=false
Categories=None;
This file will display as "Name You Want To See" and when you attempt to open it, it will run the script.sh you specify. In my case, I wrote it up to run rsync in the direction that I want (I have one for each direction - On To Deck, Off Of Deck), with the appropriate options to completely clobber the files, delete files in the destination not in the source, etc. Basically "make my files the new authoritative ones". But you could do whatever you like here, including additional pre/post work to fix things up as necessary.
But running a script like this, you basically just get a progress indicator in Desktop mode in the task bar and then it vanishes. No idea if it worked, if it didn't, etc. So what to do?
Enter: zenity
If you're not familiar with it, zenity is included in your SteamOS distro and provides an amazing suite of capability for creating informational and interactive GUI dialogs for scripts that you create.
Here's an example simple invocation:
zenity --info --title "Hello World" --text "This script just ran!" --width 300 2>/dev/null
It ends up looking something like this:
Given the touchscreen nature of the Deck, this provides a nice tactile completion notification for anything custom you want to write, just tap the Ok button to dismiss.
And it has a great side effect!
Gaming mode has an expectation that what you're about to lanch will at some point have a visual component to display for you. If you're creating scripting actions that are mostly headless, using zenity to add a completion dialog helps Gaming mode not be confused as to what happened with the launch of your script - did it crash? Was it really just supposed to run silent and exit?
By adding a GUI component, you can help keep Gaming mode from being uncertain about what you just did, even if that GUI compontent is nothing more than a big "Ok" button.
So to get your newly created manually triggered scripting actions added to Gaming mode, while you're in Desktop mode bring up your Steam Library and select Games -> Add a Non-Steam Game to My Library.
Then hit the "Browse..." button at the bottom and navigate to your already created .desktop files. Find the ones you want, Open them, then when they show up checkmarked in the list for the "Add a Game" window, finish the process with "Add Selected Programs". When you add these they'll get added to the "Uncategorized" collection by default. You can tidy this up a bit by clicking on the "four squares" looking icon at the top of your library to see all your collections and then tap "Create a new collection", give it a name, and then click "Create Collection" (not the dynamic choice). Then you can right-click on your Uncategorized entries and "Add to" your new tidy named collection to get an all-in-one place for running your scripts from within Steam.
You might ask: why are we adding the .desktop files and not the scripts themselves? Because Steam understands what these are and will automatically parse and use the display "Name" field you entered into the .desktop file to give you a nice starting point for what to call this in your Library (assuming you don't want to go whole hog and make custom artwork).
Once you've added your scripts into Steam for running, then you can flip back and try triggering them from Gaming mode.
If you've added zenity dialogs, your Deck will automatically treat that as the graphical context of your "game" (read: script) and scale it up to fill the screen nicely as appropriate.
Go wild, make some fun things!
Is there a way to just display the Console in Gaming mode as well?