리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기

Test environmentRHEL familyAlmaLinux 9.8bash 5.1root account
Shell$1$#--

Linux command-line arguments are values you pass to a program by writing them after the command name, separated by spaces. We passed options, quotes, wildcards, and -- to a test script that prints back the arguments it receives on an AlmaLinux 9 server: splitting the arguments was done by the shell, and reading the options was done by each command.

The output below is exactly what we got running bash 5.1 as root on an AlmaLinux 9.8 server. The test scripts and sample files were created in a separate working folder, and the path /home/user/www is an example value.

1️⃣ What Are Linux Command-Line Arguments?

When you type something like [command arg1 arg2] on the command line, the shell splits it into words at the spaces. The first word becomes the program to run, and the remaining words are passed to that program as its arguments, in order.

To see the passed arguments, we created args.sh in the working folder. $0 holds the name used to run it, $# holds the number of arguments, and $1 onward hold the arguments in order. The square brackets were added to show where each argument begins and ends.

#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
  echo "\$$i = [$a]"
  i=$((i+1))
done

We gave the script execute permission and ran it with three words: a, b, and c.

./args.sh a b c
$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]

The three words went into $1, $2, and $3, and $# was 3. If you run the script by writing its name after bash, $0 holds the name exactly as written, args.sh.

bash args.sh a b c
$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]

Only $0 changed to args.sh; the three arguments and the count were the same as before.

2️⃣ Command-Line Arguments and Command Options

Linux commands are usually written in the order [command -option argument]. Options change how the command behaves, and arguments specify the files, paths, or values the command works on.

ls -l /home/user/www

To the shell, -l is just another argument. When we passed the same words to args.sh, -l went into $1 and the path into $2.

./args.sh -l /home/user/www
$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]

Reading -l as an option is the job of ls. That is why the same letter means different things in different commands: -n in head sets the number of lines to print, while -n in ls prints owners as numbers instead of names.

Some options take the word right after them as their own value. In the find command, -type takes f and -name takes "*.txt" as its value; a value attached to an option like this is called an option argument.

find . -type f -name "*.txt"

In this command, the leading . is an argument not attached to any option, and it sets the folder where the search starts.

3️⃣ Linux Command Option Formats

Short options start with a single dash and are one letter long, and several of them can be written together. First, we listed the site folder in the working folder with [ls -l -a].

ls -l -a site
total 8
drwxr-xr-x 3 root root  52 Oct 28 16:00 .
drwxr-xr-x 3 root root 137 Oct 29 01:20 ..
-rw-r--r-- 1 root root  17 Oct 28 16:00 .htaccess
drwxr-xr-x 2 root root  23 Oct 28 16:00 css
-rw-r--r-- 1 root root  14 Oct 28 16:00 index.html

Next, we compared it with diff against the output of [ls -la], which joins the two letters.

diff <(ls -l -a site) <(ls -la site) && echo same
same

The two outputs did not differ by a single character. Long options start with two dashes and are written as words; --all in ls is the same option as -a, so [ls -l --all site] gave the same result as well.

Long options are accepted even if you write only the beginning, as long as it matches just one option. --al matched two options, --all and --almost-all, so ls printed no listing and exited with code 2.

ls --al site
ls: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.

Options that take a value can be written in several forms. When printing the first two lines of a.txt with head, a short option can have its value attached, as in [-n2].

head -n2 a.txt
alpha
beta

A long option joins its value with an equals sign, as in [--lines=2].

head --lines=2 a.txt
alpha
beta

All four forms, including the space-separated [-n 2] and [--lines 2], printed the two lines alpha and beta.

ls, head, and cat read their options with the getopt_long function of the C library. Looking at the three program files with strings showed that each contained this function name.

To check the same rules from the shell, use the getopt command from util-linux. Write the short options after -o and the long options after -l; a colon after a letter means the option takes a value.

getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt
 -l -a -n '2' --all -- 'a.txt'

The joined -la was split into -l and -a, and -n 2 was grouped as -n with the value 2. a.txt, which is not an option, was moved to the end after --.

4️⃣ Quoted Command-Line Arguments and Wildcards

A file name containing a space must be wrapped in quotes to be passed as a single argument.

./args.sh "my file.txt" report.txt
$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]

Without quotes, my and file.txt were split apart and $# became 3. If you pass it this way to ls or cat, they will look for two files named my and file.txt.

./args.sh my file.txt report.txt
$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]

Wildcards are turned into file names by the shell before the program receives them. When we passed *.txt in the working folder, the four files ending in .txt went in, sorted by name.

./args.sh *.txt
$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]

The quoted "*.txt" was not expanded by the shell and became a single argument, character for character. For options such as find's -name, where the program compares the pattern itself, pass the pattern quoted like this.

./args.sh "*.txt"
$0 = ./args.sh
$# = 1
$1 = [*.txt]

Empty quotes are also passed as one empty argument. Running [./args.sh '' b] gave $# as 2, with $1 empty.

5️⃣ End of Command Options (--)

An argument that starts with a dash, such as a file named -n, is read by the command as an option. When we ran [ls -n] in the dash folder, which holds only that one file, ls took -n not as a file name but as the numeric-output option and listed the folder.

ls -n
total 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -n

Arguments written after -- are not read as options, even if they start with a dash. [ls -- -n] printed only the file name -n.

ls -- -n
-n

Within a single command, the same characters are read differently before and after --. When we passed -n to cat twice, the first -n was read as the line-number option and the -n after -- as a file name, so the file's contents came out with line numbers.

cat -n -- -n
     1	dash file

You can also add a path and write it as ./-n; then the argument does not start with a dash and is read as the same -n file.

Reading -- as the end of options is also a rule on the command's side. When we passed it to args.sh, which does not read options, -- went into $1 as is.

./args.sh -- -a
$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]

The POSIX Utility Conventions specify that the first -- that is not an option argument is accepted as the end of options. That is why, with commands that follow these conventions, file names starting with - are written after --.

6️⃣ Reading Command-Line Arguments in a Shell Script

A shell script reads the arguments it receives through positional parameters and special parameters. The main(int argc, char *argv[]) of a C program receives the same arguments, so placing the two side by side looks like this.

ParameterValue it holdsC main function
$0Name of the script that was runargv[0]
$1 ~ $9First through ninth argumentsargv[1] ~ argv[9]
${10}From the tenth argument on, wrap in bracesargv[10]
$#Number of arguments, not counting $0argc - 1
"$@"All arguments, each one separateargv[1] through the end
"$*"All arguments joined into one with spaces—

A Python program receives the same arguments as the sys.argv list. Passing three arguments with [python3 -c] showed the quoted my file.txt going into a single item of the list, and -c going into the first item.

python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l
['-c', 'a', 'my file.txt', '-l']

"$@" and "$*" give different results when wrapped in double quotes. To see the difference, we created star.sh, which prints the two forms one after the other.

#!/bin/bash
echo 'with "$@"'
printf '  [%s]\n' "$@"
echo 'with "$*"'
printf '  [%s]\n' "$*"

We ran star.sh with three arguments: a, "b c", and d.

./star.sh a "b c" d
with "$@"
  [a]
  [b c]
  [d]
with "$*"
  [a b c d]

"$@" passed the three arguments separately, while "$*" joined them with spaces and passed them as one.

So when you pass the received arguments on to another command unchanged, use "$@".

shift discards $1 and moves the remaining arguments forward by one position. It is used in scripts that read one option first and treat the rest as a list of files.

We created shift.sh, which prints $1 and $# before and after shift.

#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift:  \$1 = $1, \$# = $#"

We ran shift.sh with three arguments: -v, a.txt, and b.txt.

./shift.sh -v a.txt b.txt
before shift: $1 = -v, $# = 3
after shift:  $1 = a.txt, $# = 2

From the tenth argument on, wrap the number in braces, as in ${10}. We created ten.sh, which prints $10 and ${10} side by side.

#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"

We passed 11 arguments, a through k, to ten.sh.

./ten.sh a b c d e f g h i j k
$10 = a0
${10} = j

$10 came out as a0, $1 followed by a 0, while ${10} came out as the tenth argument, j.

🔲 Command-Line Argument Simulator

In the simulator below, you can pass quotes, wildcards, and -- to args.sh, and also type commands yourself to see how ls and getopt read options and how star.sh and shift.sh receive arguments.

Command-Line Argument Simulatorbash 5.1
[root@server work]#
A virtual AlmaLinux server that runs only in your browser; args.sh prints the arguments it receives with their numbers, and ↑↓ recalls the commands you used before.

🔢 FAQ & Recommended Content

The upper limit on the combined length of arguments and environment variables is checked with [getconf ARG_MAX]; on the AlmaLinux 9.8 server it was 2097152 bytes. Above this limit, the program does not run and you get an [Argument list too long] error. When there are a great many files, do not pass them all at once with a wildcard; split them up with find's -exec or with xargs.

An argument is the actual value you pass when running a command, and a parameter is the name on the receiving side for that value. In a shell script, positional parameters such as $1 and $2 receive the arguments that were passed.

getopts, built into bash, reads short options such as -v one at a time. It does not read long options, so to accept long options such as --verbose as well, first tidy up the arguments with the getopt command used above.

ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove your humanity: 6   +   6   =