I'm fairly new to Linux and I have used batch files to do batch tasks easily. I have this script that scans the folders found inside the source folder and then creates a symbolic link off each compressed Zip archive found inside to the destination folder.

What the script does is that it goes out of the current directory twice, enters a folder called projects, then another folder called example inside and finally into a folder called release.

Within the release folder are a bunch of other folders (i.e version 1, version 2, version 3, etc.) and inside these folders is a Zip archive.

The next part of the script is that it goes through the folders version 1, version 2, version 3, etc. and then creates a symbolic file of the Zip archive found inside to the destination folder.

This for loop continues on until there are no remaining archive files to create a symbolic link of.

The script looks like this, there are comments left as a guideline:

@echo off

REM Sets the location of directories to be used in the script

REM The source folder has more folders inside with compressed ZIP archives
set source=%~dp0..\..\projects\example\release

REM The destination folder is where all the compressed ZIP archives will go to
set destination=%~dp0destination

REM A for-loop in-charge of searching for all compressed ZIP archives inside the folders in the source directory
for /D %%i in ("%source%\*") do (
    REM A for-loop that grabs every compressed ZIP archives found inside the folders in the source directory
    for %%j in ("%%~fi\*.zip") do (
        del "%destination%\%%~ni_%%~nj.zip" >nul 2>nul
        REM Creates a symbolic link for each compressed ZIP archive found to the destination directory
        mklink "%destination%\%%~ni_%%~nj.zip" "%%j" 2>nul

REM This creates a new line

REM Displays an error message that the script is not run as an administrator, and a guide for potential troubleshooting if the script is already run as an administrator
if %errorlevel% NEQ 0 echo *** ERROR! You have to run this file as administrator! ***
if %errorlevel% NEQ 0 echo *** If you are getting this error even on administrator, please create the 'destination' folder ***

REM Prompts the user for any key as an input to end the script

The directory structure and contents looks about like this:

└── Example
    └── Release
        ├── Version 1
        │   └── version1.zip
        ├── Version 2
        │   └── version2.zip
        ├── Version 3
        │   └── version3.zip
        └── Version 4
            └── version4.zip

Each symbolic link created by the script should be named in 2 parts, the first part is what folder it came from and the second part is simply project. So if it came from the Version 1 folder, the symbolic link would be called Version 1-project.zip in the destination folder.

How would I go about to converting this to a shell script? I know not every feature in a Windows batch script isn't available in bash and that's okay because I can omit some parts of the script. Thank you in advance.

  • I don't understand batch files. What files are you deleting, what files are you linking? Can you give an example?
    – choroba
    Oct 14, 2021 at 15:44
  • 1
    Yes, most of us here will have no experience with batch files. Please explain in words what you want to do and what you have so far.
    – terdon
    Oct 14, 2021 at 16:18
  • The point of the script is to exit the current directory 2 times, enter the projects folder, then the example folder and then the release folder. Within the release folder, the script will scan for compressed ZIP archives (.zip files) found within each folder inside the release folder, and then will create a symbolic link to the destination folder of each individual .zip file it finds.
    – rattle189
    Oct 14, 2021 at 16:29
  • 1
    "exit the current directory 2 times" why would you want to exit a directory? Oh, you want to change to a different directory. This needs to be written in your question as a clear set of requirements. Ignore the "how" and concentrate on the "what" and "why". An example source and corresponding expected destination can help tremendously Oct 14, 2021 at 16:30
  • 1
    Please edit your question, show us an example directory structure and contents (you can use the tree command), and then tell us what result you expect from that example. That way, we can understand what you need and be able to help you.
    – terdon
    Oct 14, 2021 at 16:34

1 Answer 1


shopt -s nullglob


mkdir -p "$destdir" || exit

for pathname in "$srcdir"/*/version*.zip; do
    name=${pathname#"$srcdir"/}    # "Version 1/version1.zip"
    name=${name%/*}-${name#*/}     # "Version 1-version1.zip"

    ln -s "$PWD/$pathname" "$destdir/$name"

The above script assumes the Example/Release directory structure you show in the question and that the files in the subdirectories are matched by version*.zip. The loop iterates over all those version*.zip files and constructs the link name using the filename and the name of the immediate parent directory. It creates the symbolic link under the $destdir directory as a symbolic link to an absolute pathname.

The two types of parameter substitutions used here are

  • ${variable#pattern}, expands to $variable with the shortest prefix string matching pattern deleted.
  • ${variable%pattern}, as above, but a suffix string is removed instead of a prefix string.

$PWD is a value maintained by the shell (the absolute pathname of the current working directory).

I'm setting the nullglob shell option for the script so that the loop does not run once if the pattern does not match (the pattern would ordinarily be left unexpanded in that case). Alternatively, you could set the failglob shell option, in the same way, to have the shell terminate with a diagnostic message instead if no names matched the pattern.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .