Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Which would be the best way in *nix (alias, script, etc) to shorten available options for a command that doesn't provide a short form?

The idea would be to wrap the command in some way be able to abbreviate just the first option. Also, allowing to use the original ones too.

Regular command:

 > command option1 file.txt
 > command option2 file.txt

Using the wrapper:

> command o1 file.txt
> command o2 file.txt

Here is some pseudocode to depict a possible solution that came to my mind by using a shell script with the same name of the command and put it first in the PATH.

 if $first_argument == "o1"
    call <command> option1 $additional_arguments
 else if $first_argument == "o2"
    call <command> option2 $additional_arguments
 else
    call <command> $first_argument $additional_arguments

Would this be possible?

share|improve this question
    
Is this for scripts of yours or to wrap existing commands? Since different commands take different styles of options (e.g. -o, -option, --option, o) it would be difficult to do something universal. –  Dennis Williamson Feb 15 '11 at 17:04
    
I'd like to wrap an specific command, the idea is to abbreviate the long options. Something like: command option1 -> command o1 –  df01 Feb 16 '11 at 19:04
    
You could define functions in your .bash_profile and do string substitution on the parameters (i.e. $@ etc.), afterwards execute that. My bash-fu is insufficient for sample code though. –  Daniel Beck Feb 16 '11 at 21:45
add comment

3 Answers

You can create aliases in your ~/.bashrc file. For example, creating a 7-zip archive of a folder, which would normally be

7z a -m0=lzma2 -mx=9 -ms=on -mf=on -mtc=on archive_name.7z folder_name

in your ~/.bashrc put in:

alias 7zipfolder='7z a -m0=lzma2 -mx=9 -ms=on -mf=on -mtc=on'

After that, you can just do,

7zipfolder archive_name.7z folder_name

You'll have to log out and back in for it to take effect, or do source ~/.bashrc

HTH :)

==== EDIT: Considering the responses below, well, I'm thinking you could do this if you modify PATH to look in your personal script folders first, like

PATH=~/.shortcommands:$PATH

And then you could create scripts with the same names as the ones that are installed in e.g. /usr/sbin, loop over all the arguments, expand the ones you want, and then end off by calling the "real" script/application in its absolute path with the translated set of options.

E.g.

  7z --folder Documents.7z Documents/

calls

  ~/.shortcommands/7z

which translates everything into:

  /usr/bin/7z a -m0=lzma2 -mx=9 -ms=on -mf=on -mtc=on Documents.7z Documents/

The script itself would be iterating over the list of arguments and then translate what would make sense to your needs. You'd probably be a long way from being able to creating a "shell" over the original command, but obviously that isn't what you're looking for. Not sure how proficient you are with bash scripting, but there are tonnes of very good resources out there. Just to serve as an example for arguments iteration, here's a snippet from a script I'm working on currently that creates/checks parity data and checksum files for other files:

# Iterate arguments while shifting off those meant for us, leaving behind files to process.
# No clue how to directly index on the arguments array, so I copy it:
args=("$@")
files=()
files_count=0

# Then we iterate over each argument, collecting anything that's for us, and adding files
# to our files array, making sure to get absolute paths should we somehow get relative ones
# (e.g. from Nautilus or the commandline):
for ((i=0; $i<$#; i++)); do
        argument=${args[$i]}
        # How deep to go into FILE before starting to create/check protection files:
        if [ "$argument" = "-d" -o "$argument" = "--depth" ]; then
                # Seek to the next argument, i.e. the value:
                let "i=i+1"
                # We'll get an error if we try to just grab the next argument and it isn't there:
                if [ $i -eq $# ]; then
                        print_argument_error "${args[$i-1]} needs a value."
                else
                        target_depth="${args[$i]}"
                        # Okay, so is the value sane?
                        if [[ ! $target_depth =~ ^[1-9][0-9]{0,}$ ]]; then
                                print_argument_error "${args[$i-1]} must be 1 or higher."
                        fi
                fi
        # Whether or not to include output from our client commands, too:
        elif [ "$argument" = "-v" -o "$argument" = "--verbose" ]; then
                print_client_output=1
        # Whether or not to verify files:
        elif [ "$argument" = "-V" -o "$argument" = "--verify" ]; then
                check=1
        # Whether or not to create validation files:
        elif [ "$argument" = "-C" -o "$argument" = "--create" ]; then
                verify=1
        # Whether or not to repair files when possible:
        elif [ "$argument" = "-R" -o "$argument" = "--repair" ]; then
                verify=1
                repair=1
        # That's all the arguments we understand, the rest must be files:
        else
                # So we assume anything but an option is an input file or dir. Get the item:
                item="$argument"

                # If it's a file, we get its directory location and convert it to absolute,
                # then prepend the file name back onto that before pushing it onto our files
                # array. If it's a dir, we just convert it to absolute before pushing it:
                if [ -f "$item" ]; then
                        dir="`dirname "$item"`"
                        files[${files_count}]="`cd "$dir"; pwd`/`basename "$item"`"
                        let "files_count=files_count+1"
                elif [ -d "$item" ]; then
                        files[${files_count}]="`cd "$item"; pwd`"
                        let "files_count=files_count+1"
                fi
        fi
done
share|improve this answer
    
Or, more specifically relating to the poster's example, alias cmdo1='command o1'. –  Daniel Beck Feb 16 '11 at 19:13
    
This could be a solution, but the command has many options which I'd like to abbreviate, and also I'd like to be able to invoke it using the long options too. –  df01 Feb 16 '11 at 19:51
    
@df01 most commands have both long and short options that do the same thing. Just use the short options where you can. Otherwise, there is no easier way to do this. –  Keith Feb 16 '11 at 21:01
add comment

It depends in part from how the command parses its options. For programs that are built using the popt argument parsing library, there's an aliasing mechanism built in, where one can create alias options that expand to existing options, using an rc file in one's home directory. Unfortunately, the popt documentation isn't exactly geared towards end users, but to developers wanting to make use of the library in their programs. However, information about /etc/popt and ${HOME}/.popt can be found in the section 3 manual page for popt in the Option Aliasing section.

This only applies to programs built to make use of popt in the first place, of course. As mentioned above, there's no universal mechanism, because there's no one argument parsing mechanism used by all programs. Wrapper scripts and aliases are the recourses for programs where there's no popt or popt-like option aliasing mechanism available.

share|improve this answer
add comment

Is this to make these easier to type? You may want to check out Programmable Command Line Completion. It can make your typing more efficient.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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