Bash - Add Symbolic Links Subdirectories
To efficiently add these symbolic links to all subdirectories that are missing them, you can use a find loop. This command will check each subdirectory and only create the link if a file or link named .env or .secret doesn't already exist.
The Command
Run this from the parent directory where your subdirectories are located:
find . -maxdepth 1 -type d ! -path . -exec sh -c '
cd "$1"
[ ! -e .env ] && ln -s /mnt/volume1/docker/shared.env .env
[ ! -e .secret ] && ln -s /mnt/volume1/docker/secret.env .secret
' _ {} \;
Breakdown of the Logic
-
find . -maxdepth 1 -type d ! -path .: This finds all directories exactly one level down from your current location, excluding the current directory (.) itself. -
-exec sh -c '...' _ {} \;: This executes a small shell script for every directory found. -
[ ! -e .env ]: This is a "logical gate." It checks if the file.envdoes not exist. If it's missing, it proceeds to the&&command to create the link. -
ln -s [target] [link_name]: Creates the symbolic link.
A Safer Alternative (Dry Run)
If you want to see which directories will be affected before actually making changes, you can use this "echo" version:
find . -maxdepth 1 -type d ! -path . -exec sh -c '
cd "$1"
[ ! -e .env ] && echo "Linking .env in $1"
[ ! -e .secret ] && echo "Linking .secret in $1"
' _ {} \;
Quick Note on Relative vs. Absolute Paths
Since you are using absolute paths for your targets (/mnt/volume1/...), these links will work regardless of which subdirectory they live in. If you ever move the docker folder, you'll need to update the links, but for a fixed mount point like yours, this is the most reliable method.
Add Folder Exceptions
To exclude specific subdirectories, you can use theĀ ! -name flag (for simple folder names) or -prune (for more complex paths).
Here are the two best ways to do it, depending on how many folders you need to skip.
Option 1: Excluding by Folder Name (Simple)
If you just want to skip a few specific folders by name (e.g., backup and logs), use this version. The ! -name "..." flags tell find to ignore those specific directories.
find . -maxdepth 1 -type d ! -path . ! -name "backup" ! -name "logs" -exec sh -c '
cd "$1"
[ ! -e .env ] && ln -s /mnt/volume1/docker/shared.env .env
[ ! -e .secret ] && ln -s /mnt/volume1/docker/secret.env .secret
' _ {} \;
Option 2: Excluding a List (Cleanest for many folders)
If you have a long list of exceptions, you can use a regex pattern. This is much easier to read and maintain. Replace folder1|folder2|folder3 with the names of the directories you want to skip.
find . -maxdepth 1 -type d ! -path . -not -regextext ".*(folder1|folder2|folder3)$" -exec sh -c '
cd "$1"
[ ! -e .env ] && ln -s /mnt/volume1/docker/shared.env .env
[ ! -e .secret ] && ln -s /mnt/volume1/docker/secret.env .secret
' _ {} \;
Pro-Tip: The "Dry Run"
I highly recommend running a "Dry Run" first to verify your exceptions are working correctly. This will print the folders it would have acted on without actually creating any links:
find . -maxdepth 1 -type d ! -path . ! -name "exclude_me" -exec echo "Processing: {}" \;
Key Flags Used
-
! -name "folder": Tells find: "Do NOT include items with this name." -
! -path .: Prevents the command from trying to create links in the current parent directory (which would fail anyway since.envlikely already exists there). -
-maxdepth 1: Ensures the command only looks at the folders right in front of you, rather than digging into sub-sub-directories.