0

I'm beginning a project that involves taking a filename from the command line as it's argument. I can't find any info on it anywhere else. I have no code yet because this is my first step.

Thanks in advance for any help. I'll be active here trying whatever tips you may have

closed as too broad by G-Man, Isaac, Archemar, dr01, h3rrmiller Feb 9 '18 at 19:23

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    You tagged your question bash and scripting. Does that mean that the program you're talking about that has to take command-line argument is supposed to be a bash script ? There's a big difference between scripts and other types of programs – Sergiy Kolodyazhnyy Feb 9 '18 at 1:45
  • hey sorry, yes, it is supposed to be script. Should have chosen the tags more carefully – Scott Holley Feb 9 '18 at 1:51
  • OK, very well. I'll post an answer soon. It will be edited later, but I think what I have in mind should get you started. – Sergiy Kolodyazhnyy Feb 9 '18 at 1:52
  • @ScottHolley: Bash is a scripting language – Jesse_b Feb 9 '18 at 1:54
  • 1
    @SergiyKolodyazhnyy. you'd be right on the money haha. I appreciate the insight though, I have this kind of convoluted project, I'm trying to really find all the info on my own because I learn by doing rather than copying code, so when I asked here, I was grateful at the really detailed responses – Scott Holley Feb 9 '18 at 2:28
1

Addressing positinal parameters

Let's clear something up first: command-line arguments when referred to bash scripts are called "positional parameters", and that's variables like $1, $2, $3 and so forth. That's the vocabulary I will be using here.

In accordance with proper shell syntax, positional parameters appear after command ( some might say duh, obviously, but syntax is important ):

command a b c

Suppose command is your script my_script.sh. From script you could execute individual commands on parameters as echo $1 and echo $2. You can also work on all of them right away via for loop. So for example, your simple script could look as so:

#!/bin/sh
# Note important difference between /bin/sh and /bin/bash
# https://askubuntu.com/q/141928/295286

echo "$1"

# for loop will substitute each $1, $2,$3 value into i each time
for i
do
    echo "$i"
done

Addressing filename part

The fact that positional parameters can be anything - numbers or text - leaves interpretation of what that's supposed to be to the author of script. If string of text is filename then naturally it must exist somewhere on filesystems ( unlike anonymous files, pipes, or sockets [need citation here] ).

Let's say you call script as my_script "this_is_my_file.txt". Simple way to test whetherthis_is_my_file.txt` is existing filename would be:

test -f "$1"

or

[ -f "$1" ]

Why ? $1 Because it's first positional parameter. Why test or [ ? Because that's the same command. From there you can use it with either

if [ -f "$1" ]; then
    echo "$1" exists
fi

or

[ -f "$1" ] && echo "$1" exists

Of course, appropriate for a good script would be to issue an error if file doesn't exist and let the script quit with that.

One of the important things in scripting is developing your own habits. Because you cannot predict what filename your user will give to script, it could be anything, which also means it could start with -. For example, -afilename. Such filenames often break scripts and regular commands which have to deal with positional parameters. In case you expect or specifically require filename to exist in current working directory, it is a good idea to use ./ before variable.

if [ -f ./"$1" ]

Even if your user explicitly puts ./ this will work anyway:

$ test -f ././input.txt && echo "YES"
YES

If we're dealing with filename that also includes path to file, that won't be a problem - the last slash before filename in /path/to/-difficult_name.txt will separate filename from rest of the path.

...to be edited and expanded later...

  • This cleared up my confusion. Your explanation of the filename segment pretty much was exactly the explanation I was looking for. One more question though. I'm using ubuntu that's operation through workspace 14, so if i'm referencing the script of the filename, then i'm assuming it needs to be within the filestems of the ubuntu os rather than my original windows os. Would it be a problem identifying it's validity otherwise? I may just be interpreting it wrong but let me know if that makes sense – Scott Holley Feb 9 '18 at 2:10
  • @ScottHolley Yes, it would need to exist within same filesystem. There are remote tools like scp and rsync that may be used to check if something exists on filesystem that is not physically attached to your computer or is part of your OS, but that's a very far fetched idea that you probably don't need for basic scripting. If you're using a virtual machine and added a shared folder to it, then you could test if file exists within the shared folder, i.e. accessible to both. Otherwise...I don't have any other ideas – Sergiy Kolodyazhnyy Feb 9 '18 at 2:18
  • 1
    Gotcha, i'm glad you got the jest of what I meant. Okay, I can work with that. Thank you – Scott Holley Feb 9 '18 at 2:22
  • @ScottHolley Linux can mount windows NTFS or FAT filesystems, so you can also access your windows files on a dual-boot linux system. There are also windows drivers to access some linux filesystems (e.g. ext2/3/4) on windows - sorry, I can't recommend any because I don't use windows often enough to need them...maybe try searching on superuser.com or softwarerecs.stackexchange.com – cas Feb 9 '18 at 9:59
0

When a script is called with arguments they are passed to the script as positional parameters. These parameters can be called using $1,$2...${10},${11} Note: brackets are required for any double digit parameter.

Additionally, $@ and $* can be used to represent all parameters, where:

($*) Expands to the positional parameters, starting from one. When the expansion is not within double quotes, each positional parameter expands to a separate word. In contexts where it is performed, those words are subject to further word splitting and pathname expansion. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c…", where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators.

and

($@) Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" …. If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed).

Here is a script that shows an example of this:

script

#!/bin/sh

echo "My arguments are $@"

echo "$1 -- $2 -- $3 -- $4 -- $5 -- $6 -- $7 -- $8 -- $9 -- $10"

echo "Correct parameter 10 is ${10}"

in action

$ ./script one two three four five six seven eight nine ten
My arguments are one two three four five six seven eight nine ten
one -- two -- three -- four -- five -- six -- seven -- eight -- nine -- one0
Correct parameter 10 is ten

Bash Reference Manual 3.4 Shell Parameters

  • 1
    Thanks, I think I can go from there. Makes more sense now. When the script is finished, i'll post it here for future askers. That's how it works right? This is my first post on Stack – Scott Holley Feb 9 '18 at 1:57
  • @ScottHolley: No this site is for questions/issues regarding unix&linux and by extension their shells/scripting languages. A question with completed code would not be appropriate. – Jesse_b Feb 9 '18 at 1:58
  • 1
    Okay, thanks for the straightforward answer. – Scott Holley Feb 9 '18 at 1:59
  • No problem. If I have not fully answered your question please let me know and I can try to elaborate more. – Jesse_b Feb 9 '18 at 2:00

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