• We did not send an email asking for donations - please read this post.

Command template for universal use in terminal?

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
Is there any way (probably a script?) to turn this command

Code:
7z a -mt -mmt=8 && exit

in something like a template which would require for me to manually enter the target file and the source dir?
Let me show you an example of what I wanna do. For instance, right now I'm repacking all of my Windows games to work in linux and when I'm done, I'm archiving them in 7z files. But it can get tiresome to write the same thing every time. So, I'd very much like to have to enter only the target and the source dir while the rest is used as a template. I'm guessing it would be some sort of a script similar to the start scripts for games but IDK enough about scripts to do it myself. It would probably be something like "7z a $targetfile $sourcedir -mt --mt=8 && exit".

So, if you understood what I'm asking, is that even possible?
 


JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,563
Reaction score
2,224
Credits
11,524
Is there any way (probably a script?) to turn this command

Code:
7z a -mt -mmt=8 && exit

in something like a template which would require for me to manually enter the target file and the source dir?
Let me show you an example of what I wanna do. For instance, right now I'm repacking all of my Windows games to work in linux and when I'm done, I'm archiving them in 7z files. But it can get tiresome to write the same thing every time. So, I'd very much like to have to enter only the target and the source dir while the rest is used as a template. I'm guessing it would be some sort of a script similar to the start scripts for games but IDK enough about scripts to do it myself. It would probably be something like "7z a $targetfile $sourcedir -mt --mt=8 && exit".

So, if you understood what I'm asking, is that even possible?

Yes, this is definitely possible!
Save the following as something like ‘7it’, make it executable with chmod and put it in your personal bin directory if you have one set up. Either ~/bin or ~/.local/bin/
Bash:
#!/usr/bin/env bash
7z a $1 $2 -mt --mt=8

Or alternatively, you could just add it to ~/.bashrc as a function:
Bash:
7it()
{
  7z a $1 $2 -mt --mt=8
}
Run it like this:
Bash:
7it /path/to/output.7z /path/to/inputDirectory

Both versions are pretty minimalist and use command line parameters. But could be expanded to do some error checking and provide usage information, if the user provides invalid parameters. I may expand that later. It’s 4am here atm! I just randomly woke up and checked my phone and somehow ended up browsing the site for a bit, ha ha!
 

wizardfromoz

Administrator
Staff member
Gold Supporter
Joined
Apr 30, 2017
Messages
7,784
Reaction score
6,608
Credits
28,633
Moving this to Command Line.

Wizard
 
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
Both versions are pretty minimalist and use command line parameters. But could be expanded to do some error checking and provide usage information, if the user provides invalid parameters. I may expand that later. It’s 4am here atm! I just randomly woke up and checked my phone and somehow ended up browsing the site for a bit, ha ha!
No need for expanding but you can add it anyway, if you feel like it. Just for information if anyone else needs it.
I saved it in a separate .sh file and this is the final result:
Code:
alias add=" '/media/1000GB/PROGRAMS/CLI HELP/7z-archiving-script/7z-script-for-alias.sh' "

Thanks!

Edit: your post helped me more than you could imagine! :) Since I'm making mods for ATS and ETS2, I started packing them as self-extracting scripts (sort of a punishment for all Windows users because almost all modders make their graphical mods to be used only on the Windows versions of these games). IDK if you know that, but making a self-extracting script requires the use of the package makeself which in turn has its own requirements with this syntax:
Code:
$ makeself --notemp ./source-directory ./script-name.sh "Unpacking..." echo "Done."
You can write whatever you want between the quotes but the creating of a self-extracting script is rather annoying bc you have to write all that every single time for every new directory you wanna make an .sh script from.
And your post spared me A LOT of writing the same thing over and over again. Using the same syntax with $1 and $2 (I think I finally understand how these two work*) I created a new bash script for makeself.

* Correct me if I'm wrong, I'm simply trying to better understand how these operators work. I THINK I know that now but still I could the opinion of someone more experienced.

So, if I'm right, $1 and $2 mean "user input 1" and "user input 2" which the terminal passes to the command in the script and once the command is completed, the cli program which participates in that script interprets the input according to what it has been instructed by its developer.
 
Last edited:

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,563
Reaction score
2,224
Credits
11,524
So, if I'm right, $1 and $2 mean "user input 1" and "user input 2" which the terminal passes to the command in the script and once the command is completed, the cli program which participates in that script interprets the input according to what it has been instructed by its developer.
Yes, If you pass parameters to a script, or to a bash function, then they are stored in local variables named $1 to $n, wnere n is the total number of parameters passed.

It seems like a long way around things, to write a script and then use an alias.
You could set up a personal bin directory for your scripts, or add a function to the end of your .bashrc - that way your script will be available as if it was an installed program.

I won't go into creating a personal bin directory here, because I've already written about it a few times in various posts here.
Here's one of them:
 
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
Yes, If you pass parameters to a script, or to a bash function, then they are stored in local variables named $1 to $n, wnere n is the total number of parameters passed.

It seems like a long way around things, to write a script and then use an alias.
You could set up a personal bin directory for your scripts, or add a function to the end of your .bashrc - that way your script will be available as if it was an installed program.

I won't go into creating a personal bin directory here, because I've already written about it a few times in various posts here.
Here's one of them:
AFAIK 'chmod +x filename.sh' makes it executable and there's an even easier way for the laziest users - right click on the file, tab "Accessibility" (Cinnamon), "Execution" - select "Everyone" and OK. That has the same effect as chmod +x.

It may seem a long way around for this but my bashrc is already quite busy. I have about 200 aliases stored there and storing the script in another file makes it easier to find, if I ever need it. Plus, if I need to change something in the script, I don't have to change the alias as well (which would require to force the terminal to update on the aliases which is one more command to execute), only the script. If I change only the script file, I won't have to force the terminal to update on aliases, thus saving myself a lot of additional typing.
 
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
..............
In order not to post a new topic, I'm gonna ask here bc what I'm gonna ask is somewhat similar to what we previously discussed.
Passing parameters by using $1, $2 and so on is when you enter them manually.
But what about if I want the output file to have the same name as the input file? Some time ago I created this alias for quicker conversion from mka (the audio track of a mkv file) to an ac3 file:

Code:
alias mka640="ffmpeg -i *.mka -vn -ar 44100 -ac 2 -ab 640k -f ac3 output640.ac3 && exit"

Usually there's just one mka file in the directory where I open the terminal, so *.mka works perfectly. But I've always wondered how to make the output ac3 file to have the same name as the input mka file. I doubt that in this case $1 will work. Clearly that's gonna be another cli script, but that's as far as my ideas go.
 

wizardfromoz

Administrator
Staff member
Gold Supporter
Joined
Apr 30, 2017
Messages
7,784
Reaction score
6,608
Credits
28,633
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
The instruction on stackoverflow was a bit more clear, so if I have understood it correctly, it should be something like this:
Code:
#!/usr/bin/env bash

for f in *.mka;
do
    ffmpeg -i "$f" -vn -ar 44100 -ac 2 -ab 640k -f ac3 "${f%}".ac3;
done

I'm gonna test it now to see if I did understand it, cuz this looks like programming to me.

Edit: Yes, it works. I wish the output file could be inputfilename.ac3 instead of inputfilename.mka.ac3 but whatever, the point is that I did get it right.

Thanks, Wiz! :)
 
Last edited:
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
After @JasKinasis pointed me in the right direction (again - a big thanks for that :) ), I uploaded the scripts on Google for backup and started experimenting with them. It didn't take me long to discover I can simplify them even further. As I've already established, $1 and $2 mean "user input 1" and "user input 2". So I simplified two of the scripts even further.

This was the 7z script before I simplified it:
Code:
7z a $1 $2 -mx -mmt=8
meaning that I had to manually type the file name, the extension and the directory name with a backslash in order to avoid bash confusion (the latter might be a bug, but it doesn't matter).

This is what the new 7z script looks like after I simplified it:
Code:
7z a $1.7z $1/ -mx -mmt=8
With the simplified script now I have to type one thing only (usually just paste it in the terminal, after the alias): the source directory name. That way the target archive has the same as the directory name. It works, I tested it.

Then I simplified another script:
Code:
mkisofs -o $1 $2

and it became like this:
Code:
mkisofs -o $1.iso $1/
I'm sure I don't have to explain what this one does. :) No worries, it works like a charm. I always test such things to see if they work.

And here comes what puzzles me:
Code:
makeself --notemp $1 $2 "Unpacking." echo "Done."

For those who don't know that is, makeself a CLI tool that creates self extracting sh archives. You probably have seen a similar option in 7z for Windows: "create self extractive archive". Well, this tool does the same, only with an sh extension, instead of an exe. This tool is expecting a syntax like this:
Code:
makeself --notemp /sourcedirname /sourcedirname.sh [message during extraction] echo [message when extraction is complete]

So basically it's expecting user input 1 and 2. And here's what puzzles me: it's expecting user input 1 and 2, so I decided to simplify it the same way I simplified the other two scripts above by rewriting the script into

Code:
makeself --notemp /$1 /$1.sh "Unpacking." echo "Done."

but for some reason that doesn't work. If I open the terminal in the parent directory where the source directory is located in order to test the new script (for instance, I open the terminal in ~/.local/share, where the "applications" directory is the source directory) and when I execute this script, it says "applications directory doesn't exist".

So I'm puzzled as to why this doesn't work, when the same method worked just fine with the other two scripts. It's probably something quite simple that I'm missing in this case, but I have no idea what that might be, so I'm open to suggestions.
 
Last edited:

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,563
Reaction score
2,224
Credits
11,524
After @JasKinasis pointed me in the right direction (again - a big thanks for that :) ), I uploaded the scripts on Google for backup and started experimenting with them. It didn't take me long to discover I can simplify them even further. As I've already established, $1 and $2 mean "user input 1" and "user input 2". So I simplified two of the scripts even further.

This was the 7z script before I simplified it:
Code:
7z a $1 $2 -mx -mmt=8
meaning that I had to manually type the file name, the extension and the directory name with a backslash in order to avoid bash confusion (the latter might be a bug, but it doesn't matter).

This is what the new 7z script looks like after I simplified it:
Code:
7z a $1.7z $1/ -mx -mmt=8
With the simplified script now I have to type one thing only (usually just paste it in the terminal, after the alias): the source directory name. That way the target archive has the same as the directory name. It works, I tested it.

Then I simplified another script:
Code:
mkisofs -o $1 $2

and it became like this:
Code:
mkisofs -o $1.iso $1/
I'm sure I don't have to explain what this one does. :) No worries, it works like a charm. I always test such things to see if they work.

And here comes what puzzles me:
Code:
makeself --notemp $1 $2 "Unpacking." echo "Done."

For those who don't know that is, makeself a CLI tool that creates self extracting sh archives. You probably have seen a similar option in 7z for Windows: "create self extractive archive". Well, this tool does the same, only with an sh extension, instead of an exe. This tool is expecting a syntax like this:
Code:
makeself --notemp /sourcedirname /sourcedirname.sh [message during extraction] echo [message when extraction is complete]

So basically it's expecting user input 1 and 2. And here's what puzzles me: it's expecting user input 1 and 2, so I decided to simplify it the same way I simplified the other two scripts above by rewriting the script into

Code:
makeself --notemp /$1 /$1.sh "Unpacking." echo "Done."

but for some reason that doesn't work. If I open the terminal in the parent directory where the source directory is located in order to test the new script (for instance, I open the terminal in ~/.local/share, where the "applications" directory is the source directory) and when I execute this script, it says "applications directory doesn't exist".

So I'm puzzled as to why this doesn't work, when the same method worked just fine with the other two scripts. It's probably something quite simple that I'm missing in this case, but I have no idea what that might be, so I'm open to suggestions.

If you’re passing something like applications to your script as $1 and in your script, you’re setting the path to: /$1
That means that the path will expand to:
/applications. And I’m guessing you don’t have a directory at /applications/, which is why you’re getting the error.

Try this instead:
makeself —notemp "$1" "$1.sh" "unpacking…." echo "Done."

That way you should be able to pass a relative, or absolute path to the script to specify the directory to package up.
 
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
Yes, that worked, thanks. :) It's weird, though, that bash treats the backslash one way and makeself treats it differently.

The file manager I use (PCManFM) can open a terminal inside a directory, so I manually navigate to ~/.local/share and press F4 in it. The effect is the same as typing "cd ~/.local/share". And since bash has a long time standing glitch, a few years ago I discovered that if I don't type the dir name with the backslash in front of it, bash will say such a file OR directory doesn't exist. That's why ever since then I have to type (for instance) /applications instead of just applications.

Offtopic: what did you type as a bbcode to wrap the "/applications/" text in a mini-code tag (one that wraps only the word and doesn't reach the end of the line)?
 

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,563
Reaction score
2,224
Credits
11,524

KGIII

Super Moderator
Staff member
Gold Supporter
Joined
Jul 23, 2020
Messages
7,349
Reaction score
6,334
Credits
59,574
And since bash has a long time standing glitch, a few years ago I discovered that if I don't type the dir name with the backslash in front of it, bash will say such a file OR directory doesn't exist.

When writing my articles, I tend to use ~/Downloads (for example), but that's because folks may already have a terminal open and in a different directory.

But, if I'm in ~/, I can just type "cd Downloads" and enter the Downloads directory just fine. I don't need the slash at the front of it or anything. If I'm in ~/Downloads and want to go to the ~/Music directory, I can't just type 'cd Music', because that directory doesn't exist inside the ~/Downloads directory.

Which is to say, I'm not really seeing your bug. It works even if I'm already in ~/Downloads. Inside that directory, I can 'cd foo' to enter the ~/Downloads/foo directory if said directory exists.
 
OP
rado84

rado84

Well-Known Member
Joined
Feb 25, 2019
Messages
647
Reaction score
518
Credits
3,613
I was talking about directories that exist in the dir you're in and about any operations upon these directories. Changing dir works even without a backslash.

Also, sometimes copying to a dir won't work even with an -r option and you have to put a backslash at the end of the name. The same applies when creating directories.

They may have fixed these problems at some point but old habits die hard, so I'm still using the workarounds.
 
$100 Digital Ocean Credit
Get a free VM to test out Linux!

Linux.org Hosting Donations
Consider making a donation

Members online


Top