xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

Linux shell script function All In One

Linux shell script function All In One

shell 脚本函数

shell script function

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

# shell script 函数的定义格式
# [可选项], 方括号内的都是可选项 ✅
[ function ] funname [()] {
    commands;
    [return int;]
}
  1. 可以带关键字 function _name() 定义,也可以直接 func_name() 定义, 不能带任何参数 ⚠️。
  2. 参数返回,可以显示加关键字 return 返回,如果不加 return ,默认将以最后一条命令运行结果的退出状态码,作为返回值。 return 后跟整数数值 n (0-255)
  3. 如何给函数传递参数,直接跟在调用函数名的后面即可, 如 function_name arg1 arg2 ... arg2
  4. 在函数内部可以使用 $0 ~ $N, 读取传入的参数

image

https://www.runoob.com/linux/linux-shell-func.html

shell script 函数定义的 3 种方式

  1. name()

name 函数名 + () 括号 ✅ (类似 Python function 🎉)

# shell script function
is_same_file () {
 test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")";
}
  1. function name

function 关键字 + name 函数名 ✅

# 等价于,关键字 function name {}
function is_same_file {
  # 使用 $0 ~ $N 接收函数的参数列表 ✅
  # 返回值,是最后一行命令的执行结果的退出状态码 ✅
  return test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")";
}
  1. function name() { commands } ⚠️

⚠️ 不推荐使用这种方式,可能存在兼容性问题,不同的 shell 支持情况不同

二合一: function 关键字 + name 函数名 + () 括号 ✅ (类似 JavaScript function 🎉)

# 等价于,关键字 function name() {}
function is_same_file () {
  # 使用 $0 ~ $N 接收函数的参数列表 ✅
  # 返回值,是最后一行命令的执行结果的退出状态码 ✅
  return test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")";
}

(亲测:bash ✅ / zsh ✅)

https://www.gnu.org/software/bash/manual/html_node/Shell-Functions.html

https://linux.xgqfrms.xyz/linux_basic/0340bashshell-scripts.htm#function

test

$ if is_same_file student.sh hard; then echo yes; else echo no; fi
# yes
$ if is_same_file student.sh soft; then echo yes; else echo no; fi
# no

error

软链接自动指向原文件 bug ❌

eric@rpi4b:~ $ ls -ali | grep test
 24553 -rw-r--r--  1 eric eric   411  9月 21 11:37 nvm_echo_test.sh
 30221 -rwxr-xr-x  1 eric eric   172  9月 21 18:03 shell-env-variable-test.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test-hard-link.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test.sh
 23662 lrwxrwxrwx  1 eric eric     7 10月  8 16:44 test-soft-link.sh -> test.sh
eric@rpi4b:~ $ ./file-ef-check.sh 
./test.sh -ef ./test-soft-link.sh
yes ✅
./test.sh -ef ./test-hard-link.sh
yes ✅

#!/usr/bin/env bash

echo "./test.sh -ef ./test-soft-link.sh"

if [ ./test.sh -ef ./test-soft-link.sh ]; then
  echo "yes ✅"
else
  echo "no ❌"
fi

echo "./test.sh -ef ./test-hard-link.sh"
if [ ./test.sh -ef ./test-hard-link.sh ]; then
  echo "yes ✅"
else
  echo "no ❌"
fi


# echo "./student.sh -ef ./soft"
# if [ ./student.sh -ef ./soft ]; then
#   echo "yes ✅"
# else
#   echo "no ❌"
# fi

# echo "./student.sh -ef ./hard"
# if [ ./student.sh -ef ./hard ]; then
#   echo "yes ✅"
# else
#   echo "no ❌"
# fi

<<EOF

eric@rpi4b:~ $ ls -ail | grep test
 24553 -rw-r--r--  1 eric eric   411  9月 21 11:37 nvm_echo_test.sh
 30221 -rwxr-xr-x  1 eric eric   172  9月 21 18:03 shell-env-variable-test.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test-hard-link.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test.sh
 23662 lrwxrwxrwx  1 eric eric     7 10月  8 16:44 test-soft-link.sh -> test.sh


EOF

image

solution

#!/usr/bin/env bash

# 单方括号 [] ✅
echo "[ ./test.sh -ef ./test-demo.sh ]"
if [ ./test.sh -ef ./test-demo.sh ]; then
  echo "yes ✅"
else
  echo "no ❌"
fi

# 双方括号 [[]] ✅
echo "[[ ./test.sh -ef ./test-demo.sh ]]"
if [[ ./test.sh -ef ./test-demo.sh ]]; then
  echo "yes ✅"
else
  echo "no ❌"
fi


# 软链接 bug ❌ 自动指向原文件

echo "./test.sh -ef ./test-soft-link.sh"
# if [ ./test.sh -ef ./test-soft-link.sh ]; then
if [[ ./test.sh -ef ./test-soft-link.sh ]]; then
  echo "yes ✅"
else
  echo "no ❌"
fi

echo "./test.sh -ef ./test-hard-link.sh"
# if [ ./test.sh -ef ./test-hard-link.sh ]; then
if [[ ./test.sh -ef ./test-hard-link.sh ]]; then
  echo "yes ✅"
else
  echo "no ❌"
fi


# echo "./student.sh -ef ./soft"
# if [ ./student.sh -ef ./soft ]; then
#   echo "yes ✅"
# else
#   echo "no ❌"
# fi

# echo "./student.sh -ef ./hard"
# if [ ./student.sh -ef ./hard ]; then
#   echo "yes ✅"
# else
#   echo "no ❌"
# fi

<<EOF

eric@rpi4b:~ $ ls -ali | grep test
 24553 -rw-r--r--  1 eric eric   411  9月 21 11:37 nvm_echo_test.sh
 30221 -rwxr-xr-x  1 eric eric   172  9月 21 18:03 shell-env-variable-test.sh
 30331 -rwxr-xr-x  1 eric eric    47 10月 25 00:26 test-demo.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test-hard-link.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test.sh
 23662 lrwxrwxrwx  1 eric eric     7 10月  8 16:44 test-soft-link.sh -> test.sh
 
EOF


image

# use the keyword `function`
function is_same_file () {
  # The return value is the exit status code
  # of the execution result of the last line of command.
  return test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")";
}

if is_same_file ./test.sh ./test-demo.sh; then echo "yes ✅"; else echo "no ❌"; fi
if is_same_file ./test.sh ./test-hard-link.sh; then echo "yes ✅"; else echo "no ❌"; fi
if is_same_file ./test.sh ./test-soft-link.sh; then echo "yes ✅"; else echo "no ❌"; fi

# -bash: return: test:需要数字参数 ❌

image

fix $(command)

# use the keyword `function`
function is_same_file () {
  # The return value is the exit status code
  # of the execution result of the last line of command.
  # $(command) ✅
  return $(test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")");
}
eric@rpi4b:~ $ ls -ali | grep test
 24553 -rw-r--r--  1 eric eric   411  9月 21 11:37 nvm_echo_test.sh
 30221 -rwxr-xr-x  1 eric eric   172  9月 21 18:03 shell-env-variable-test.sh
 30331 -rwxr-xr-x  1 eric eric    47 10月 25 00:26 test-demo.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test-hard-link.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test.sh
 23662 lrwxrwxrwx  1 eric eric     7 10月  8 16:44 test-soft-link.sh -> test.sh
 
eric@rpi4b:~ $ function is_same_file () {
  # The return value is the exit status code
  # of the execution result of the last line of command.
  # $(command) ✅
  return $(test "$(stat -c "%d %i" "$1")" = "$(stat -c "%d %i" "$2")");
}
eric@rpi4b:~ $ if is_same_file ./test.sh ./test-demo.sh; then echo "yes ✅"; else echo "no ❌"; fi
no ❌
eric@rpi4b:~ $ if is_same_file ./test.sh ./test-hard-link.sh; then echo "yes ✅"; else echo "no ❌"; fi
yes ✅
eric@rpi4b:~ $ if is_same_file ./test.sh ./test-soft-link.sh; then echo "yes ✅"; else echo "no ❌"; fi
no ❌
eric@rpi4b:~ $ 

image

https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html

https://www.runoob.com/linux/linux-shell-passing-arguments.html

demos

bug

# ❌ inode is different
$ [ ./student.sh -ef ./soft ] && echo yes || echo no
yes

$ [ ./student.sh -ef ./hard ] && echo yes || echo no
yes

#!/usr/bin/env bash

echo "./student.sh -ef ./soft"

# if [ ./student.sh -ef ./soft ]; then
if [ ./test.sh -ef ./test-soft-link.sh ]; then
  echo "yes"
else
  echo "no"
fi

echo "./student.sh -ef ./hard"

# if [ ./student.sh -ef ./hard ]; then
if [ ./test.sh -ef ./test-hard-link.sh ]; then
  echo "yes"
else
  echo "no"
fi


<<EOF

eric@rpi4b:~ $ ls -ail | grep test
 24553 -rw-r--r--  1 eric eric   411  9月 21 11:37 nvm_echo_test.sh
 30221 -rwxr-xr-x  1 eric eric   172  9月 21 18:03 shell-env-variable-test.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test-hard-link.sh
 24592 -rwxr-xr-x  2 eric eric   156  9月 21 13:15 test.sh
 23662 lrwxrwxrwx  1 eric eric     7 10月  8 16:44 test-soft-link.sh -> test.sh

EOF

(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

man test

FILE1 -ef FILE2

FILE1 and FILE2 have the same device and inode numbers

test 使用 -ef 比较两个文件是否相等

$ man test

$ man test > man-test.md

$ cat man-test.md
TEST(1)                                   User Commands                                  TEST(1)

NAME
       test - check file types and compare values

SYNOPSIS
       test EXPRESSION
       test
       [ EXPRESSION ]
       [ ]
       [ OPTION

DESCRIPTION
       Exit with the status determined by EXPRESSION.

       --help display this help and exit

       --version
              output version information and exit

       An omitted EXPRESSION defaults to false.  Otherwise, EXPRESSION is true or false and sets
       exit status.  It is one of:

       ( 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)

       -N FILE
              FILE exists and has been modified since it was last read

       -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

       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: Binary -a and -o are inherently ambiguous.  Use 'test EXPR1 && test EXPR2' or 'test
       EXPR1 || test EXPR2' instead.

       NOTE:  [ honors the --help and --version options, but test does not.  test treats each of
       those as it treats any other nonempty STRING.

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

AUTHOR
       Written by Kevin Braunsdorf and Matthew Bradburn.

REPORTING BUGS
       GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
       Report any translation bugs to <https://translationproject.org/team/>

COPYRIGHT
       Copyright © 2020 Free Software Foundation, Inc.  License GPLv3+: GNU  GPL  version  3  or
       later <https://gnu.org/licenses/gpl.html>.
       This is free software: you are free to change and redistribute it.  There is NO WARRANTY,
       to the extent permitted by law.

SEE ALSO
       Full documentation <https://www.gnu.org/software/coreutils/[>
       or available locally via: info '(coreutils) test invocation'

GNU coreutils 8.32                       September 2020                                  TEST(1)
eric@rpi4b:~/Desktop $ 

man stat

$ man stat

$ man stat > man-stat.md

$ cat man-stat.md
$ cat ./Desktop/man-stat.md
STAT(1)                                   User Commands                                  STAT(1)

NAME
       stat - display file or file system status

SYNOPSIS
       stat [OPTION]... FILE...

DESCRIPTION
       Display file or file system status.

       Mandatory arguments to long options are mandatory for short options too.

       -L, --dereference
              follow links

       -f, --file-system
              display file system status instead of file status

       --cached=MODE
              specify  how to use cached attributes; useful on remote file systems. See MODE be‐
              low

       -c  --format=FORMAT
              use the specified FORMAT instead of the default; output a newline after  each  use
              of FORMAT

       --printf=FORMAT
              like  --format,  but  interpret  backslash  escapes, and do not output a mandatory
              trailing newline; if you want a newline, include \n in FORMAT

       -t, --terse
              print the information in terse form

       --help display this help and exit

       --version
              output version information and exit

       The --cached MODE argument can be; always, never, or default.  `always` will  use  cached
       attributes  if  available,  while  `never`  will  try  to synchronize with the latest at‐
       tributes, and `default` will leave it up to the underlying file system.

       The valid format sequences for files (without --file-system):

       %a     permission bits in octal (note '#' and '0' printf flags)

       %A     permission bits and file type in human readable form

       %b     number of blocks allocated (see %B)

       %B     the size in bytes of each block reported by %b

       %C     SELinux security context string

       %d     device number in decimal

       %D     device number in hex

       %f     raw mode in hex

       %F     file type

       %g     group ID of owner

       %G     group name of owner

       %h     number of hard links

       %i     inode number

       %m     mount point

       %n     file name

       %N     quoted file name with dereference if symbolic link

       %o     optimal I/O transfer size hint

       %s     total size, in bytes

       %t     major device type in hex, for character/block device special files

       %T     minor device type in hex, for character/block device special files

       %u     user ID of owner

       %U     user name of owner

       %w     time of file birth, human-readable; - if unknown

       %W     time of file birth, seconds since Epoch; 0 if unknown

       %x     time of last access, human-readable

       %X     time of last access, seconds since Epoch

       %y     time of last data modification, human-readable

       %Y     time of last data modification, seconds since Epoch

       %z     time of last status change, human-readable

       %Z     time of last status change, seconds since Epoch

       Valid format sequences for file systems:

       %a     free blocks available to non-superuser

       %b     total data blocks in file system

       %c     total file nodes in file system

       %d     free file nodes in file system

       %f     free blocks in file system

       %i     file system ID in hex

       %l     maximum length of filenames

       %n     file name

       %s     block size (for faster transfers)

       %S     fundamental block size (for block counts)

       %t     file system type in hex

       %T     file system type in human readable form

   --terse is equivalent to the following FORMAT:
              %n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o %C

   --terse --file-system is equivalent to the following FORMAT:
              %n %i %l %t %s %S %b %f %a %c %d

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

AUTHOR
       Written by Michael Meskes.

REPORTING BUGS
       GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
       Report any translation bugs to <https://translationproject.org/team/>

COPYRIGHT
       Copyright © 2020 Free Software Foundation, Inc.  License GPLv3+: GNU  GPL  version  3  or
       later <https://gnu.org/licenses/gpl.html>.
       This is free software: you are free to change and redistribute it.  There is NO WARRANTY,
       to the extent permitted by law.

SEE ALSO
       stat(2), statfs(2), statx(2)

       Full documentation <https://www.gnu.org/software/coreutils/stat>
       or available locally via: info '(coreutils) stat invocation'

GNU coreutils 8.32                       September 2020                                  STAT(1)

refs

https://www.cnblogs.com/xgqfrms/p/17728141.html#5221859

https://stackoverflow.com/questions/76408365/why-does-the-linux-shell-command-test-ef-not-work-on-soft-links-as-its-manual-d



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2023-10-25 07:54  xgqfrms  阅读(4)  评论(5编辑  收藏  举报