Linux test command and

Linux. Команда test

Предназначена для проверки типа файла и сравнения чисел и строк. Возвращает код возврата 0 (истина) или 1 (ложь) в зависимости от вычисления выражения. Выражения могут быть как унарными, так и бинарными.

Для сокращения кода сценария используют парный оператор [ как синоним test . Парный оператор требует пробела между скобками потому, что [ (скобка) является командой оболочки.

Проверка типа файла

  • -d file — истина, если file существует и является каталогом
  • -e file — истина, если file существует
  • -f file — истина, если file существует и является обычным файлом
  • -r file — истина, если file существует и доступен для чтения
  • -s file — истина, если file существует и имеет размер больше, чем ноль
  • -w file — истина, если file существует и доступен для записи
  • -x file — истина, если file существует и доступен для выполнения
  • -L file — истина, если file существует и является символьной ссылкой
  • file1 -nt file2 — истина, если file1 новее (дата модификации), чем file2
  • file1 -ot file2 — истина, если file1 старее, чем file2

Сравнение строк

  • -z string — истина, если длина string равна нулю
  • -n string — истина, если длина string не ноль
  • string1 = string2 — истина, если строки равны
  • string1 != string2 — истина, если строки не равны

Сравнение целых чисел

  • число1 -eq число2 — истина, если число1 равно число2
  • число1 -gt число2 — истина, если число1 больше число2
  • число1 -ge число2 — истина, если число1 больше или равно число2
  • число1 -lt число2 — истина, если число1 меньше число2
  • число1 -le число2 — истина, если число1 меньше или равно число2
  • число1 -ne число2 — истина, если число1 не равно число2

Операции AND и OR

  • expr1 -a expr2 — истина, если оба выражения expr1 и expr2 истина (операция AND)
  • expr1 -o expr2 — истина, если хотя бы одно из выражений expr1 или expr2 истина (операция OR)
  • ! expr — истина, если выражение expr ложно

В условном выражении команды test можно использовать круглые скобки, чтобы изменить порядок вычисления, но их нужно экранировать:

« [[…]] » — расширенный вариант от « […] », оболочка выполняет его как один элемент с кодом возврата. Внутри « [[…]] » разрешается выполнение операторов && , || которые приводят к ошибке в обычных скобках « […] ».

Источник

Linux test command

On Unix-like operating systems, the test command checks file types and compares values.

This page covers the GNU/Linux version of test.

For information about the test command in bash see our bash test command page.

Description

test is used as part of the conditional execution of shell commands.

test exits with the status determined by EXPRESSION. Placing the EXPRESSION between square brackets ([ and ]) is the same as testing the EXPRESSION with test. To see the exit status at the command prompt, echo the value «$?» A value of 0 means the expression evaluated as true, and a value of 1 means the expression evaluated as false.

Syntax

Expressions

Expressions take the following forms:

( EXPRESSION ) EXPRESSION is true
! EXPRESSION EXPRESSION is false
EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true
-n STRING the length of STRING is nonzero
STRING equivalent to -n STRING
-z STRING the length of STRING is zero
STRING1 = STRING2 the strings are equal
STRING1 != STRING2 the strings are not equal
INTEGER1 -eq INTEGER2 INTEGER1 is equal to INTEGER2
INTEGER1 -ge INTEGER2 INTEGER1 is greater than or equal to INTEGER2
INTEGER1 -gt INTEGER2 INTEGER1 is greater than INTEGER2
INTEGER1 -le INTEGER2 INTEGER1 is less than or equal to INTEGER2
INTEGER1 -lt INTEGER2 INTEGER1 is less than INTEGER2
INTEGER1 -ne INTEGER2 INTEGER1 is not equal to INTEGER2
FILE1 -ef FILE2 FILE1 and FILE2 have the same device and inode numbers
FILE1 -nt FILE2 FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2 FILE1 is older than FILE2
-b FILE FILE exists and is block special
-c FILE FILE exists and is character special
-d FILE FILE exists and is a directory
-e FILE FILE exists
-f FILE FILE exists and is a regular file
-g FILE FILE exists and is set-group-ID
-G FILE FILE exists and is owned by the effective group ID
-h FILE FILE exists and is a symbolic link (same as -L)
-k FILE FILE exists and has its sticky bit set
-L FILE FILE exists and is a symbolic link (same as -h)
-O FILE FILE exists and is owned by the effective user ID
-p FILE FILE exists and is a named pipe
-r FILE FILE exists and read permission is granted
-s FILE FILE exists and has a size greater than zero
-S FILE FILE exists and is a socket
-t FD file descriptor FD is opened on a terminal
-u FILE FILE exists and its set-user-ID bit is set
-w FILE FILE exists and write permission is granted
-x FILE FILE exists and execute (or search) permission is granted
Читайте также:  Python установленные модули linux

Except for -h and -L, all FILE-related tests dereference symbolic links. Beware that parentheses need to be escaped (e.g., by backslashes) for shells. INTEGER may also be -l STRING, which evaluates to the length of STRING.

NOTE: your shell may have its own version of test, which usually supersedes the version described here. Please refer to your shell’s documentation for details about the options it supports.

Examples

This command prints the text «Yes, that’s true.» because 100 is greater than 99.

This command prints the text «No.» because 100 is not less than 99.

This command prints «» because the expression is true; the two strings are identical.

This command prints «1» because the expression is false; 5 does not equal 6.

Источник

The classic test command

General syntax

This command allows you to do various tests and sets its exit code to 0 (TRUE) or 1 (FALSE) whenever such a test succeeds or not. Using this exit code, it’s possible to let Bash react on the result of such a test, here by using the command in an if-statement:

The syntax of the test command is relatively easy. Usually it’s the command name » test » followed by a test type (here » -e » for «file exists») followed by test-type-specific values (here the filename to check, » /etc/passwd «).

There’s a second standardized command that does exactly the same: the command » [ » — the difference just is that it’s called » [ » and the last argument to the command must be a » ] «: It forms » [ ] «

Let’s rewrite the above example to use it: One might think now that these «[» and «]» belong to the syntax of Bash’s if-clause: No they don’t! It’s a simple, ordinary command, still!

Another thing you have to remember is that if the test command wants one parameter for a test, you have to give it one parameter. Let’s check for some of your music files: As you definitely noted, the filename contains spaces. Since we call a normal ordinary command («test» or «[«) the shell will word-split the expansion of the variable mymusic : You need to quote it when you don’t want the test -command to complain about too many arguments for this test-type! If you didn’t understand it, please read the article about words.

Please also note that the file-tests want one filename to test. Don’t give a glob (filename-wildcards) as it can expand to many filenames ⇒ too many arguments!

Another common mistake is to provide too few arguments: This provides exactly one test-argument to the command. With one parameter, it defaults to the -n test: It tests if a provided string is empty ( FALSE ) or not ( TRUE ) — due to the lack of spaces to separate the arguments the shown command always ends TRUE !

Well, I addressed several basic rules, now let’s see what the test-command can do for you. The Bash test-types can be split into several sections: file tests, string tests, arithmetic tests, misc tests. Below, the tests marked with are non-standard tests (i.e. not in SUS/POSIX/etc..).

File tests

This section probably holds the most tests, I’ll list them in some logical order. Since Bash 4.1, all tests related to permissions respect ACLs, if the underlying filesystem/OS supports them.

Operator syntax Description
-a True if exists. (not recommended, may collide with -a for AND , see below)
-e True if exists.
-f True, if exists and is a regular file.
-d True, if exists and is a directory.
-c True, if exists and is a character special file.
-b True, if exists and is a block special file.
-p True, if exists and is a named pipe (FIFO).
-S True, if exists and is a socket file.
-L True, if exists and is a symbolic link.
-h True, if exists and is a symbolic link.
-g True, if exists and has sgid bit set.
-u True, if exists and has suid bit set.
-r True, if exists and is readable.
-w True, if exists and is writable.
-x True, if exists and is executable.
-s True, if exists and has size bigger than 0 (not empty).
-t True, if file descriptor is open and refers to a terminal.
-nt True, if is newer than (mtime).
-ot True, if is older than (mtime).
-ef True, if and refer to the same device and inode numbers.
Читайте также:  Joomla псевдоним пункта меню

String tests

Operator syntax Description
-z True, if is empty.
-n True, if is not empty (this is the default operation).
= True, if the strings are equal.
!= True, if the strings are not equal.
True if sorts before lexicographically (pure ASCII , not current locale!). Remember to escape! Use \
> True if sorts after lexicographically (pure ASCII , not current locale!). Remember to escape! Use \>

Arithmetic tests

Operator syntax Description
-eq True, if the integers are equal.
-ne True, if the integers are NOT equal.
-le True, if the first integer is less than or equal second one.
-ge True, if the first integer is greater than or equal second one.
-lt True, if the first integer is less than second one.
-gt True, if the first integer is greater than second one.

Misc syntax

Operator syntax Description
-a True, if and are true (AND). Note that -a also may be used as a file test (see above)
-o True, if either or is true (OR).
! True, if is false (NOT).
( ) Group a test (for precedence). Attention: In normal shell-usage, the «(» and «)» must be escaped; use «\(» and «\)»!
-o True, if the shell option is set.
-v True if the variable has been set. Use var[n] for array elements.
-R True if the variable has been set and is a nameref variable (since 4.3-alpha)

Number of Arguments Rules

The test builtin, especially hidden under its [ name, may seem simple but is in fact causing a lot of trouble sometimes. One of the difficulty is that the behaviour of test not only depends on its arguments but also on the number of its arguments.

Here are the rules taken from the manual ( Note: This is for the command test , for [ the number of arguments is calculated without the final ] , for example [ ] follows the «zero arguments» rule):

These rules may seem complex, but it’s not so bad in practice. Knowing them might help you to explain some of the «unexplicable» behaviours you might encounter:

This code prints «var is not empty», even though -n something is supposed to be true if $var is not empty — why?

Here, as $var is not quoted, word splitting occurs and $var results in actually nothing (Bash removes it from the command’s argument list!). So the test is in fact [ -n ] and falls into the «one argument» rule, the only argument is «-n» which is not null and so the test returns true. The solution, as usual, is to quote the parameter expansion: [ -n «$var» ] so that the test has always 2 arguments, even if the second one is the null string.

These rules also explain why, for instance, -a and -o can have several meanings.

AND and OR

The Prefered Way

The way often recommended to logically connect several tests with AND and OR is to use several single test commands and to combine them with the shell && and || list control operators.

The return status of AND and OR lists is the exit status of the last command executed in the list

The other way: -a and -o

The logical operators AND and OR for the test-command itself are -a and -o , thus:

They are not && or || :

You might find the error message confusing, [ does not find the required final ] , because as seen above && is used to write a list of commands. The if statement actually sees two commands:

…which must fail.

Why you should avoid using -a and -o

If portability is a concern

POSIX®/SUSv3 does not specify the behaviour of test in cases where there are more than 4 arguments. If you write a script that might not be executed by Bash, the behaviour might be different! 1)

If you want the cut behaviour

Let’s say, we want to check the following two things (AND):

Let’s see: ⇒ The arguments are all expanded before test runs, thus the echo-command is executed.

⇒ Due to the nature of the && list operator, the second test-command runs only if the first test-command returns true, our echo-command is not executed.

Note: In my opinion, -a and -o are also less readable [pgas]

Precedence and Parenthesis

Take care if you convert your scripts from using -a and -o to use the list way ( && and || ):

That means, you can get different results, depending on the manner of use: As a result you have to think about it a little or add precedence control (parenthesis).

For && and || parenthesis means (shell-ly) grouping the commands, and since ( … ) introduces a subshell we will use < … >instead:

For the test command, the precedence parenthesis are, as well, ( ) , but you need to escape or quote them, so that the shell doesn’t try to interpret them:

As for AND and OR, there are 2 ways to negate a test with the shell keyword ! or passing ! as an argument to test .

Here ! negates the exit status of the command test which is 0 (true), and the else part is executed:

Here the test command itself exits with status 1 (false) and the else is also executed:

Unlike for AND and OR, both methods for NOT have an identical behaviour, at least for doing one single test.

Pitfalls summarized

In this section you will get all the mentioned (and maybe more) possible pitfalls and problems in a summary.

General

Here’s the copy of a mail on bug-bash list. A user asking a question about using the test command in Bash, he’s talking about a problem, which you may have already had yourself:

See the problem regarding the used test-command (the other potential problems are not of interest here)? He simply didn’t know that test or [ is a normal, simple command. Well, here’s the answer he got. I quote it here, because it’s a well written text that addresses most of the common issues with the «classic» test command:

I hope this text protects you a bit from stepping from one pitfall into the next.

I find it very interesting and informative, that’s why I quoted it here. Many thanks, Bob, also for the permission to copy the text here!

Code examples

Snipplets

Some code snipplets follow, different ways of shell reaction is used.

Listing directories

Using a for-loop to iterate through all entries of a directory, if an entry is a directory ( [ -d «$fn» ] ), print its name:

See also

Discussion

Thanks for an interesting and helpful explanation of the sources and requirements of the test operators. Even after 20 years, I’m still learning!

What I’d like to know is how to avoid one of the most common pitfalls of the file and directory tests (-f and -d in particular). This is the strange behaviour when you test a hidden file, or a file starting with ‘.’ (not just a file that isn’t readable by the permissions applied to it).

In this case, although the file can be listed and passed as an argument to both test types («if [[ -d» and «if test -d»), both tests fail when passed a ‘dot’ file.

So far, all the workarounds I’ve seen are quite cumbersome, and detract from «nice» shell scripting. Can you help with an example, or explain why these tests apparently ‘fail’ the way they do, and what we can do to get them to work with all files?

can you explain more what you mean by failing with dot-files? A dot-file is «hidden» by a convention to not display it (ls, file explorers, …), not technically hidden (i.e. there is no «hidden» flag).

For the permissions thing, it’s relatively easy to explain. Just give me an example of what’s unclear.

Thanks, Jan, I appreciate the help!

OK, here’s the actual example of the problem I’m seeing.

I have a directory in my home directory. In that subdirectory is only one item, a directory called «.git», which contains a number of files and folders, which I want to search (without using find). This search is part of a general search, but for some reason it never seemed to search the .git folder!

I wrote a little recursive-function script that cd’s into each directory, then for each file in the directory, I use the following exact code (minus some printing functions that only get executed outside the folder test):

I set $StartPath to, say, ‘.’ to begin with, and kick the script off in my home directory.

It works as expected for all the folders it finds — but when it gets to the folder containing the .git folder, although the first echo command echoes the dot folder (so it’s not being hidden by the ls options or anything, that’s why I set the dotglob shell option), the -d test always fails for that folder, and the second echo command never executes, even though it’s an actual folder, is readable, and so on.

This happens for any «.folder» — except, if I test by using -d ‘.foldername’ on the command line, it works!

I’m sure this is something really silly I’m misunderstanding, but I’ll be darned if I can figure it out. Any ideas, or suggestions?

I thought it might be the use of the «.» as the parameter to ls in the function call… but removing it had no effect on this issue, and I want to be able to extend the code and use that as another parameter later on. That’s as much as I could figure out might be causing the issue.

Any help is very much appreciated! It’s driving me nuts, it’s a good thing not many of the files I want to find are beneath .folders!

Источник

Поделиться с друзьями
КомпСовет
Adblock
detector