├── .gitignore ├── original_source ├── commands │ ├── start.txt │ └── builtin │ │ ├── start.txt │ │ ├── return.txt │ │ ├── exit.txt │ │ ├── readonly.txt │ │ ├── export.txt │ │ ├── wait.txt │ │ ├── cd.txt │ │ ├── shopt.txt │ │ ├── local.txt │ │ ├── trap.txt │ │ ├── kill.txt │ │ ├── exec.txt │ │ ├── caller.txt │ │ ├── shift.txt │ │ └── echo.txt ├── syntax │ ├── start.txt │ ├── ccmd │ │ ├── start.txt │ │ ├── grouping_subshell.txt │ │ ├── arithmetic_eval.txt │ │ ├── until_loop.txt │ │ ├── intro.txt │ │ ├── while_loop.txt │ │ ├── grouping_plain.txt │ │ ├── user_select.txt │ │ └── if_clause.txt │ ├── grammar │ │ └── start.txt │ └── expansion │ │ ├── start.txt │ │ ├── wordsplit.txt │ │ ├── arith.txt │ │ ├── tilde.txt │ │ └── intro.txt ├── howto │ ├── start.txt │ ├── testing-your-scripts.txt │ └── collapsing_functions.txt ├── scripting │ ├── tutoriallist.txt │ └── tutoriallist │ │ └── bashguide.txt ├── user │ ├── start.txt │ └── thebonsai │ │ └── imprint.txt ├── dict │ └── terms │ │ ├── symlink.txt │ │ ├── special_file.txt │ │ ├── posix.txt │ │ ├── directory.txt │ │ ├── filetimes.txt │ │ ├── shell.txt │ │ ├── file.txt │ │ ├── globbing.txt │ │ ├── interpreter_directive.txt │ │ ├── end_of_options.txt │ │ ├── hardlink.txt │ │ └── parameter.txt ├── snipplets │ ├── pause_command.txt │ ├── filesize.txt │ ├── start.txt │ ├── ssh_local_var.txt │ ├── screen_saverestore.txt │ ├── ssh_fetchkeys.txt │ ├── xclip.txt │ ├── awkcsv.txt │ ├── prargs.txt │ ├── largestfile.txt │ ├── kill_bg_job_without_message.txt │ ├── wrapperargs.txt │ └── add_color_to_your_scripts.txt ├── snipplet.txt ├── misc │ ├── shell_humor.txt │ └── readthesourceluke.txt ├── meta │ └── need_love.txt └── wishes.txt ├── requirements.txt ├── docs ├── tags.md ├── dict │ ├── symlink.md │ ├── special_file.md │ ├── posix.md │ ├── directory.md │ ├── filetimes.md │ ├── shell.md │ ├── file.md │ ├── globbing.md │ ├── interpreter_directive.md │ ├── end_of_options.md │ ├── hardlink.md │ └── parameter.md ├── snipplets │ ├── index.md │ ├── filesize.md │ ├── pause_command.md │ ├── ssh_local_var.md │ ├── screen_saverestore.md │ ├── ssh_fetchkeys.md │ ├── xclip.md │ ├── awkcsv.md │ ├── prargs.md │ ├── largestfile.md │ ├── kill_bg_job_without_message.md │ ├── wrapperargs.md │ └── add_color_to_your_scripts.md ├── commands │ └── builtin │ │ ├── return.md │ │ ├── exit.md │ │ ├── readonly.md │ │ ├── export.md │ │ ├── wait.md │ │ ├── shopt.md │ │ ├── cd.md │ │ ├── kill.md │ │ ├── trap.md │ │ ├── local.md │ │ ├── exec.md │ │ ├── caller.md │ │ ├── shift.md │ │ └── echo.md ├── syntax │ ├── ccmd │ │ ├── grouping_subshell.md │ │ ├── arithmetic_eval.md │ │ ├── until_loop.md │ │ ├── intro.md │ │ ├── while_loop.md │ │ ├── user_select.md │ │ ├── grouping_plain.md │ │ └── if_clause.md │ └── expansion │ │ ├── wordsplit.md │ │ ├── arith.md │ │ ├── tilde.md │ │ └── intro.md ├── misc │ ├── shell_humor.md │ ├── readthesourceluke.md │ └── bashphorisms.md └── howto │ ├── testing-your-scripts.md │ └── collapsing_functions.md ├── .editorconfig ├── .github └── workflows │ └── deploy.yml ├── scripts └── generate-diff-links.sh ├── overrides └── partials │ └── comments.html ├── mkdocs.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | site 2 | env -------------------------------------------------------------------------------- /original_source/commands/start.txt: -------------------------------------------------------------------------------- 1 | ====== Commands ====== 2 | 3 | -------------------------------------------------------------------------------- /original_source/commands/builtin/start.txt: -------------------------------------------------------------------------------- 1 | ====== Builtin Commands ====== 2 | -------------------------------------------------------------------------------- /original_source/syntax/start.txt: -------------------------------------------------------------------------------- 1 | ====== Syntax ====== 2 | 3 | {{indexmenu>:syntax#10#sort+title}} -------------------------------------------------------------------------------- /original_source/howto/start.txt: -------------------------------------------------------------------------------- 1 | ====== HOWTO ====== 2 | 3 | 4 | {{indexmenu>:howto#10#sort+title}} -------------------------------------------------------------------------------- /original_source/syntax/ccmd/start.txt: -------------------------------------------------------------------------------- 1 | ====== Compound Commands ====== 2 | 3 | {{indexmenu>:syntax:ccmd#10#sort+title}} 4 | -------------------------------------------------------------------------------- /original_source/syntax/grammar/start.txt: -------------------------------------------------------------------------------- 1 | ====== Syntax: Grammar ====== 2 | 3 | {{indexmenu>:syntax:grammar#10#sort+title}} 4 | 5 | -------------------------------------------------------------------------------- /original_source/syntax/expansion/start.txt: -------------------------------------------------------------------------------- 1 | ====== Syntax: Expansions ====== 2 | 3 | {{indexmenu>:syntax:expansion#10#sort+title}} 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material 2 | mkdocs-git-revision-date-localized-plugin 3 | mkdocs-awesome-pages-plugin 4 | mkdocs-minify-plugin 5 | -------------------------------------------------------------------------------- /docs/tags.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: [navigation] 3 | --- 4 | 5 | # Tags 6 | 7 | Following is a list of all existing tags: 8 | 9 | [TAGS] 10 | -------------------------------------------------------------------------------- /original_source/scripting/tutoriallist.txt: -------------------------------------------------------------------------------- 1 | IntelliMindz offers [[Ansys Training in Chennai]https://intellimindz.com/ansys-training-in-chennai/] to help users learn and use this tool effectively. Our course content is from “Getting Started Courses” to deep diving into learning topics. IntelliMindz Ansys Training in Chennai will validate the knowledge and skills needed to work with all Ansys tools. Enroll Now!!! to explore more concepts in it. -------------------------------------------------------------------------------- /original_source/user/start.txt: -------------------------------------------------------------------------------- 1 | Best PHP Training Institute in Chennai 2 | 3 | https://intellimindz.com/php-training-in-chennai/ 4 | 5 | If you are looking for the best PHP training institute, look no further than Intellimindz in Chennai. The best PHP training in Chennai with highly qualified and experienced trainers. Our PHP courses are designed in such a way that trainees can understand each concept instantly. Call us at 09655877677 to schedule a free DEMO now. 6 | 7 | -------------------------------------------------------------------------------- /docs/dict/symlink.md: -------------------------------------------------------------------------------- 1 | # Symlink 2 | 3 | A symlink (symbolic link) is a \"normal\" file, which contains a pointer 4 | to another filename. Since it really only points to another **filename** 5 | it can 6 | 7 | - reference filenames on other filesystems 8 | - reference filenames that don't actually exist 9 | - save a reference to the name of a directory 10 | 11 | ## See also 12 | 13 | - [hardlink](../dict/hardlink.md) 14 | - [directory](../dict/directory.md) 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # https://editorconfig.org/ 4 | 5 | 6 | root = true 7 | 8 | [*] 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | max_line_length = 100 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | 21 | [*.{conf,html,py}] 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /docs/snipplets/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - bash 4 | - shell 5 | - scripting 6 | - code 7 | - download 8 | - snipplet 9 | - example 10 | --- 11 | 12 | # Small code snipplets 13 | 14 | These snipplets are **not** meant as HowTo or Tutorial or FAQ. 15 | Mostly they are only a line of code and a short comment. 16 | 17 | See it more like an initial idea to give you a start. 18 | 19 | 24 | -------------------------------------------------------------------------------- /original_source/dict/terms/symlink.txt: -------------------------------------------------------------------------------- 1 | ====== Symlink ====== 2 | 3 | A symlink (symbolic link) is a "normal" file, which contains a pointer to another filename. Since it really only points to another **filename** it can 4 | * reference filenames on other filesystems 5 | * reference filenames that don't actually exist 6 | * save a reference to the name of a directory 7 | 8 | ===== See also ===== 9 | * [[dict:terms:hardlink | hardlink]] 10 | * [[dict:terms:filesystem | filesystem]] 11 | * [[dict:terms:directory | directory]] 12 | -------------------------------------------------------------------------------- /docs/dict/special_file.md: -------------------------------------------------------------------------------- 1 | # Special file 2 | 3 | Unlike a regular file (a bunch of accessible data organized on a 4 | filesystem), it's a special filename that points to a ressource or 5 | similar: 6 | 7 | - character special files 8 | - block special files 9 | - named pipes 10 | - socket files 11 | 12 | Since a directory also is only a file, you can count it as special file, 13 | too. 14 | 15 | ## See also 16 | 17 | - [file](../dict/file.md) 18 | - [filename](../dict/hardlink.md) 19 | - [directory](../dict/directory.md) 20 | -------------------------------------------------------------------------------- /original_source/dict/terms/special_file.txt: -------------------------------------------------------------------------------- 1 | ====== Special file ====== 2 | 3 | Unlike a regular file (a bunch of accessible data organized on a filesystem), it's a special filename that points to a ressource or similar: 4 | * character special files 5 | * block special files 6 | * named pipes 7 | * socket files 8 | Since a directory also is only a file, you can count it as special file, too. 9 | 10 | ===== See also ===== 11 | * [[dict:terms:file | file]] 12 | * [[dict:terms:hardlink | filename]] 13 | * [[dict:terms:directory | directory]] -------------------------------------------------------------------------------- /original_source/snipplets/pause_command.txt: -------------------------------------------------------------------------------- 1 | ====== Pausing a script (like MSDOS pause command) ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: terminal, pause, input 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Jan Schampera 7 | type: snipplet 8 | ---- 9 | 10 | From the [[commands:builtin:read#examples|example section of the read command]], something that acts similar to the MSDOS ''pause'' command: 11 | 12 | 13 | pause() { 14 | local dummy 15 | read -s -r -p "Press any key to continue..." -n 1 dummy 16 | } 17 | 18 | -------------------------------------------------------------------------------- /original_source/scripting/tutoriallist/bashguide.txt: -------------------------------------------------------------------------------- 1 | ====== Bash guide on Greg's wiki ====== 2 | 3 | ---- dataentry tutorial ---- 4 | type : tutorial 5 | title : Bash guide on Greg's wiki 6 | website_urls : http://wooledge.org:8000/BashGuide 7 | contact : Lhunath 8 | recindex : 90 9 | ---- 10 | 11 | ===== Details ===== 12 | 13 | This guide teaches modern stuff and good practises. I recommend to learn from it. It was written by the guys in #bashIRC channel on Freenode (mainly lhunath), because there are so many bad tutorials out there. -------------------------------------------------------------------------------- /original_source/snipplets/filesize.txt: -------------------------------------------------------------------------------- 1 | ====== Show size of a file ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: files, file size 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Frank Lazzarini 7 | type: snipplet 8 | ---- 9 | 10 | This is a simple snippet to echo the size of a file in bytes. 11 | 12 | 13 | #!/bin/bash 14 | FILENAME=/home/heiko/dummy/packages.txt 15 | FILESIZE=$(wc -c < "$FILENAME") 16 | # non standard way (GNU stat): FILESIZE=$(stat -c%s "$FILENAME") 17 | 18 | echo "Size of $FILENAME = $FILESIZE bytes." 19 | 20 | -------------------------------------------------------------------------------- /docs/dict/posix.md: -------------------------------------------------------------------------------- 1 | # POSIX 2 | 3 | POSIX(r) is a family of standards defined by the IEEE to give a minimum 4 | API and interface standardization across the variants of UNIX(r) 5 | operating systems. 6 | 7 | One part of it is the standardization of minimum functionality and 8 | behaviour of the system shell and some utilities (commands). 9 | 10 | - UNIX is a registered trademark of The Open Group in the US and other 11 | countries. 12 | - POSIX is a registered trademark of the IEEE Inc. 13 | 14 | ## See also 15 | 16 | - Dictionary, internal: [shell](../dict/shell.md) 17 | -------------------------------------------------------------------------------- /docs/snipplets/filesize.md: -------------------------------------------------------------------------------- 1 | # Show size of a file 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: files, file size 4 | LastUpdate_dt: 2010-07-31 Contributors: Frank Lazzarini type: snipplet 5 | 6 | ------------------------------------------------------------------------ 7 | 8 | This is a simple snippet to echo the size of a file in bytes. 9 | 10 | #!/bin/bash 11 | FILENAME=/home/heiko/dummy/packages.txt 12 | FILESIZE=$(wc -c < "$FILENAME") 13 | # non standard way (GNU stat): FILESIZE=$(stat -c%s "$FILENAME") 14 | 15 | echo "Size of $FILENAME = $FILESIZE bytes." 16 | -------------------------------------------------------------------------------- /docs/snipplets/pause_command.md: -------------------------------------------------------------------------------- 1 | # Pausing a script (like MSDOS pause command) 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: terminal, pause, input 4 | LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera type: snipplet 5 | 6 | ------------------------------------------------------------------------ 7 | 8 | From the [example section of the read 9 | command](../commands/builtin/read.md#examples), something that acts similar 10 | to the MSDOS `pause` command: 11 | 12 | pause() { 13 | local dummy 14 | read -s -r -p "Press any key to continue..." -n 1 dummy 15 | } 16 | -------------------------------------------------------------------------------- /original_source/dict/terms/posix.txt: -------------------------------------------------------------------------------- 1 | ====== POSIX ====== 2 | 3 | POSIX(r) is a family of standards defined by the IEEE to give a minimum API and interface standardization across the variants of UNIX(r) operating systems. 4 | 5 | One part of it is the standardization of minimum functionality and behaviour of the system shell and some utilities (commands). 6 | 7 | * UNIX is a registered trademark of The Open Group in the US and other countries. 8 | * POSIX is a registered trademark of the IEEE Inc. 9 | 10 | ===== See also ===== 11 | * Dictionary, internal: [[dict:terms:shell]] 12 | 13 | -------------------------------------------------------------------------------- /docs/dict/directory.md: -------------------------------------------------------------------------------- 1 | # Directory 2 | 3 | In terms of UNIX(r), a directory is a special file which contains a list 4 | of [hardlinks](../dict/hardlink.md) to other files. These other files 5 | also can be directories of course, so it's possible to create a 6 | \"hierarchy of directories\" - the UNIX(r)-typical filesystem structure. 7 | 8 | The structure begins at the special directory `/` (root directory) and 9 | all other directory entries are **subdirectories** of it. 10 | 11 | ## See also 12 | 13 | - [hardlink](../dict/hardlink.md) 14 | - [file](../dict/file.md) 15 | - [special file](../dict/special_file.md) 16 | -------------------------------------------------------------------------------- /original_source/dict/terms/directory.txt: -------------------------------------------------------------------------------- 1 | ====== Directory ====== 2 | 3 | In terms of UNIX(r), a directory is a special file which contains a list of [[dict:terms:hardlink | hardlinks]] to other files. These other files also can be directories of course, so it's possible to create a "hierarchy of directories" - the UNIX(r)-typical filesystem structure. 4 | 5 | The structure begins at the special directory ''/'' (root directory) and all other directory entries are **subdirectories** of it. 6 | 7 | 8 | ===== See also ===== 9 | * [[dict:terms:hardlink | hardlink]] 10 | * [[dict:terms:file | file]] 11 | * [[dict:terms:special_file | special file]] 12 | -------------------------------------------------------------------------------- /docs/dict/filetimes.md: -------------------------------------------------------------------------------- 1 | # File timestamp 2 | 3 | ## atime 4 | 5 | This timestamp indicates when a file was last accessed (read). `cat`ing 6 | a file or executing a shellscript will set it, for example. 7 | 8 | ## ctime 9 | 10 | This timestamp is set, whenever the metadata of a file (stored in the 11 | responsible inode) is set. The metadata includes for example: 12 | 13 | - file name 14 | - fize size 15 | - file mode (permissions) 16 | 17 | and some other things. `ctime` will also be updated when a file is 18 | written to (when `mtime` is updated. 19 | 20 | ## mtime 21 | 22 | The mtime is set, whenever a file's contents are changed, for example 23 | by editing a file. 24 | -------------------------------------------------------------------------------- /original_source/snipplet.txt: -------------------------------------------------------------------------------- 1 | ~~NOTOC~~ 2 | ~~DISCUSSION:off~~ 3 | 4 | ====== Small code snipplets ====== 5 | 6 | {{keywords>bash shell scripting code download snipplet example}} 7 | 8 | These snipplets are **not** meant as HowTo or Tutorial or FAQ. Mostly they are only a line of code and a short comment. 9 | 10 | See it more like an initial idea to give you a start. 11 | 12 | ===== List of snipplets ===== 13 | 14 | * [[snipplets:start|reset filter]] 15 | 16 | ---- datacloud snipplet ---- 17 | field: snipplet_tags 18 | ---- 19 | 20 | 21 | ---- datatable snipplet ---- 22 | cols : %pageid%, LastUpdate_dt 23 | headers : Snipplet, Last updated 24 | sort : %pageid% 25 | ---- 26 | -------------------------------------------------------------------------------- /original_source/dict/terms/filetimes.txt: -------------------------------------------------------------------------------- 1 | ====== File timestamp ====== 2 | 3 | ===== atime ===== 4 | This timestamp indicates when a file was last accessed (read). ''cat''ing a file or executing a shellscript will set it, for example. 5 | 6 | 7 | 8 | ===== ctime ===== 9 | This timestamp is set, whenever the metadata of a file (stored in the responsible inode) is set. The metadata includes for example: 10 | * file name 11 | * fize size 12 | * file mode (permissions) 13 | and some other things. ''ctime'' will also be updated when a file is written to (when ''mtime'' is updated. 14 | 15 | ===== mtime ===== 16 | The mtime is set, whenever a file's contents are changed, for example by editing a file. 17 | 18 | -------------------------------------------------------------------------------- /original_source/dict/terms/shell.txt: -------------------------------------------------------------------------------- 1 | ====== Shell ====== 2 | 3 | On UNIX(r), the shell is the main interaction tool between the user-level and the system. That doesn't necessarily mean the user always sits infront of a shell, but it's integral part of the system, not only an "optional commandline interpreter". 4 | 5 | The main job of a shell is to execute commands as a user requests them. This behaviour alone doesn't help much. A shell knits some intelligence and flow control around the possibility to execute commands - it's a complete commandline-oriented user-interface (UI). 6 | 7 | FIXME 8 | 9 | ===== See also ===== 10 | 11 | ===== See also (external) ===== 12 | * Wikipedia: [[http://en.wikipedia.org/wiki/Unix_shell | UNIX shell]] -------------------------------------------------------------------------------- /original_source/snipplets/start.txt: -------------------------------------------------------------------------------- 1 | ~~NOTOC~~ 2 | ~~DISCUSSION:off~~ 3 | 4 | ====== Small code snippets ====== 5 | 6 | {{keywords>bash shell scripting code download snippet example}} 7 | 8 | These snippets are **not** meant as HowTo or Tutorial or FAQ. Mostly they are only a line of code and a short comment. 9 | 10 | See them more as an initial idea or starting point rather than a tutorial. 11 | 12 | ===== List of snippets ===== 13 | 14 | [[snipplets:start|reset filter]] 15 | 16 | ---- datacloud snippet ---- 17 | field: snipplet_tags 18 | ---- 19 | 20 | 21 | ---- datatable snippet ---- 22 | cols : %pageid%, LastUpdate_dt 23 | headers : Snipplet, Last updated 24 | sort : %pageid% 25 | filter : type=snipplet 26 | ---- 27 | -------------------------------------------------------------------------------- /original_source/snipplets/ssh_local_var.txt: -------------------------------------------------------------------------------- 1 | ====== Run some bash commands with SSH remotely using local variables ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: ssh, variables 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: cweiss 7 | type: snipplet 8 | ---- 9 | 10 | In this example, we want to make sure a certain file exists on the remote server: 11 | 12 | 13 | file=/tmp/file.log 14 | ssh ${options} ${login} "if [ ! -e '$file' ] ; then touch '$file' ; fi" 15 | 16 | 17 | Notice the command is surrounded by double quotes, and the $file variable is surrounded by single quotes. That has the effect to be wordsplit-proof in the local shell (due to the double-quotes) and in the remote shell (due to the single-quotes). 18 | 19 | -------------------------------------------------------------------------------- /docs/dict/shell.md: -------------------------------------------------------------------------------- 1 | # Shell 2 | 3 | On UNIX(r), the shell is the main interaction tool between the 4 | user-level and the system. That doesn't necessarily mean the user 5 | always sits infront of a shell, but it's integral part of the system, 6 | not only an \"optional commandline interpreter\". 7 | 8 | The main job of a shell is to execute commands as a user requests them. 9 | This behaviour alone doesn't help much. A shell knits some intelligence 10 | and flow control around the possibility to execute commands - it's a 11 | complete commandline-oriented user-interface (UI). 12 | 13 | !!! warning "FIXME" 14 | tbd. 15 | 16 | ## See also 17 | 18 | ## See also (external) 19 | 20 | - Wikipedia: [UNIX shell](http://en.wikipedia.org/wiki/Unix_shell) 21 | -------------------------------------------------------------------------------- /docs/dict/file.md: -------------------------------------------------------------------------------- 1 | # File 2 | 3 | A file is a pool of data in the `filesystem`. On 4 | userlevel, it's referenced using a name, a 5 | [hardlink](hardlink.md) to the file. 6 | 7 | If a file is not referenced anymore (number of hardlinks to it drops to 8 | 1) then the space allocated for that file is re-used, unless it's still 9 | used by some process. 10 | 11 | The file-data splits into actual payload (file contents) and some 12 | metadata like filesize, filemode or timestamps. The metadata is stored 13 | in the `inode`. 14 | 15 | Strictly spoken, a [hardlink](hardlink.md) (also called 16 | \"filename\") points to the `inode` which organizes a 17 | file, not to the file itself. 18 | 19 | ## See also 20 | 21 | - [filetimes](filetimes.md) 22 | - [hardlink](hardlink.md) 23 | -------------------------------------------------------------------------------- /docs/snipplets/ssh_local_var.md: -------------------------------------------------------------------------------- 1 | # Run some bash commands with SSH remotely using local variables 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: ssh, variables 4 | LastUpdate_dt: 2010-07-31 Contributors: cweiss type: snipplet 5 | 6 | ------------------------------------------------------------------------ 7 | 8 | In this example, we want to make sure a certain file exists on the 9 | remote server: 10 | 11 | file=/tmp/file.log 12 | ssh ${options} ${login} "if [ ! -e '$file' ] ; then touch '$file' ; fi" 13 | 14 | Notice the command is surrounded by double quotes, and the \$file 15 | variable is surrounded by single quotes. That has the effect to be 16 | wordsplit-proof in the local shell (due to the double-quotes) and in the 17 | remote shell (due to the single-quotes). 18 | -------------------------------------------------------------------------------- /original_source/snipplets/screen_saverestore.txt: -------------------------------------------------------------------------------- 1 | ====== Save and restore terminal/screen content ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: terminal, restore screen 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Greg Wooledge 7 | type: snipplet 8 | ---- 9 | 10 | This cool hack uses the terminal capabilities (see ''terminfo(5)'' manual) **smcup** and **rmcup** to save and restore the terminal content. 11 | 12 | 13 | For sure, you’ve already seen those programs that restore the terminal contents after they did their work (like ''vim''). 14 | 15 | 16 | # save, clear screen 17 | tput smcup 18 | clear 19 | 20 | # example "application" follows... 21 | read -n1 -p "Press any key to continue..." 22 | # example "application" ends here 23 | 24 | # restore 25 | tput rmcup 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy to GitHub Pages 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | permissions: 8 | contents: write 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-python@v4 15 | with: 16 | python-version: 3.x 17 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV 18 | - uses: actions/cache@v3 19 | with: 20 | key: mkdocs-material-${{ env.cache_id }} 21 | path: .cache 22 | restore-keys: | 23 | mkdocs-material- 24 | - run: pip install mkdocs-material mkdocs-git-revision-date-localized-plugin mkdocs-awesome-pages-plugin mkdocs-minify-plugin 25 | - run: mkdocs gh-deploy --force 26 | -------------------------------------------------------------------------------- /docs/snipplets/screen_saverestore.md: -------------------------------------------------------------------------------- 1 | # Save and restore terminal/screen content 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: terminal, restore 4 | screen LastUpdate_dt: 2010-07-31 Contributors: Greg Wooledge type: 5 | snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | This cool hack uses the terminal capabilities (see `terminfo(5)` manual) 10 | **smcup** and **rmcup** to save and restore the terminal content. 11 | 12 | For sure, you've already seen those programs that restore the terminal 13 | contents after they did their work (like `vim`). 14 | 15 | # save, clear screen 16 | tput smcup 17 | clear 18 | 19 | # example "application" follows... 20 | read -n1 -p "Press any key to continue..." 21 | # example "application" ends here 22 | 23 | # restore 24 | tput rmcup 25 | -------------------------------------------------------------------------------- /docs/commands/builtin/return.md: -------------------------------------------------------------------------------- 1 | # The return builtin command 2 | 3 | ## Synopsis 4 | 5 | return [N] 6 | 7 | ## Description 8 | 9 | The `return` command returns from a shell function. 10 | 11 | If `N` is given, the return code to the caller is set to `N`. If not, 12 | the returned status the the status of the most recently executed command 13 | (i.e. `$?`). 14 | 15 | ### Options 16 | 17 | There are no options. 18 | 19 | ### Exit status 20 | 21 | If everything is okay, the `return` command doesn't come back. If it 22 | comes back, there was a problem in doing the return. 23 | 24 | |Status|Reason| 25 | |-|-| 26 | |1|`return` was called while not being in a shell function or sourced file| 27 | 28 | ## Examples 29 | 30 | ## Portability considerations 31 | 32 | ## See also 33 | 34 | - [The exit builtin command](../../commands/builtin/exit.md) 35 | - [The exit status](../../dict/exit_status.md) 36 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/grouping_subshell.md: -------------------------------------------------------------------------------- 1 | # Grouping commands in a subshell 2 | 3 | ## Synopsis 4 | 5 | ( ) 6 | 7 | ## Description 8 | 9 | The [list](../../syntax/basicgrammar.md#lists) `` is executed in a 10 | separate shell - a subprocess. No changes to the environment (variables 11 | etc...) are reflected in the "main shell". 12 | 13 | ## Examples 14 | 15 | Execute a command in a different directory. 16 | 17 | ``` bash 18 | echo "$PWD" 19 | ( cd /usr; echo "$PWD" ) 20 | echo "$PWD" # Still in the original directory. 21 | ``` 22 | 23 | ## Portability considerations 24 | 25 | - The subshell compound command is specified by POSIX. 26 | - Avoid ambiguous syntax. 27 | 28 | ``` bash 29 | (((1+1))) # Equivalent to: (( (1+1) )) 30 | ``` 31 | 32 | ## See also 33 | 34 | - [grouping commands](../../syntax/ccmd/grouping_plain.md) 35 | - [Subshells on Greycat's wiki](http://mywiki.wooledge.org/SubShell) 36 | -------------------------------------------------------------------------------- /original_source/dict/terms/file.txt: -------------------------------------------------------------------------------- 1 | ====== File ====== 2 | 3 | A file is a pool of data in the [[dict:terms:filesystem | filesystem]]. On userlevel, it's referenced using a name, a [[dict:terms:hardlink | hardlink]] to the file. 4 | 5 | If a file is not referenced anymore (number of hardlinks to it drops to 0) then the space allocated for that file is re-used, unless it's still used by some process. 6 | 7 | The file-data splits into actual payload (file contents) and some metadata like filesize, filemode or timestamps. The metadata is stored in the [[dict:terms:inode | inode]]. 8 | 9 | Strictly spoken, a [[dict:terms:hardlink | hardlink]] (also called "filename") points to the [[dict:terms:inode | inode]] which organizes a file, not to the file itself. 10 | 11 | 12 | ===== See also ===== 13 | * [[dict:terms:filesystem | filesystem]] 14 | * [[dict:terms:filetimes | filetimes]] 15 | * [[dict:terms:hardlink | hardlink]] 16 | * [[dict:terms:inode | inode]] 17 | -------------------------------------------------------------------------------- /scripts/generate-diff-links.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | GIT_HASH="${1:-50aeb31ff80e7bdde9b8edd50ab924e3791fe606}" 7 | 8 | BASE_LOCAL_URL="http://127.0.0.1:8000/bash-hackers-wiki/" 9 | BASE_DEPLOY_URL="https://flokoe.github.io/bash-hackers-wiki/" 10 | BASE_ARCHIVE_URL="https://web.archive.org/web/20230127020427/https://wiki.bash-hackers.org/" 11 | 12 | # Table Headers 13 | cat << EOF 14 | |Filename|Local Version|Deployed Version|Archive Version| 15 | |--|--|--|--| 16 | EOF 17 | 18 | for file in $(git show --name-only "${GIT_HASH}" | grep md$); do 19 | filename_no_docs_prefix="${file#*docs/}" 20 | filename_no_ext="${filename_no_docs_prefix%.*}" 21 | echo "|"${filename_no_docs_prefix} \ 22 | "|[${filename_no_ext}](${BASE_LOCAL_URL}${filename_no_ext})" \ 23 | "|[${filename_no_ext}](${BASE_DEPLOY_URL}${filename_no_ext})" \ 24 | "|[${filename_no_ext}](${BASE_ARCHIVE_URL}${filename_no_ext})|" 25 | done 26 | 27 | -------------------------------------------------------------------------------- /original_source/commands/builtin/return.txt: -------------------------------------------------------------------------------- 1 | ====== The return builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | return [N] 5 | 6 | ===== Description ===== 7 | The ''return'' command returns from a shell function. 8 | 9 | If ''N'' is given, the return code to the caller is set to ''N''. If not, the returned status the the status of the most recently executed command (i.e. ''$?''). 10 | 11 | ==== Options ==== 12 | There are no options. 13 | 14 | 15 | ==== Exit status ==== 16 | 17 | If everything is okay, the ''return'' command doesn't come back. If it comes back, there was a problem in doing the return. 18 | 19 | ^Status ^Reason ^ 20 | |1 |''return'' was called while not being in a shell function or sourced file | 21 | 22 | 23 | ===== Examples ===== 24 | 25 | 26 | ===== Portability considerations ===== 27 | 28 | ===== See also ===== 29 | * [[commands:builtin:exit|The exit builtin command]] 30 | * [[dict:terms:exit_status|The exit status]] 31 | -------------------------------------------------------------------------------- /original_source/snipplets/ssh_fetchkeys.txt: -------------------------------------------------------------------------------- 1 | ====== Fetching SSH hostkeys without interaction ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: ssh, ssh-keys 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Jan Schampera 7 | ---- 8 | 9 | Applies at least to ''openssh''. 10 | 11 | To get the hostkeys for a server, and write them to ''known_hosts''-file (to avoid that yes/no query when the key isn't known), you can do: 12 | 13 | 14 | ssh-keyscan -t rsa foo foo.example.com 1.2.3.4 >> ~/.ssh/known_host 15 | 16 | 17 | This example queries the hostkeys for the very same machine, but under 3 different "names" (hostname, FQDN, IP) and redirects the output to the ''known_hosts''-file. 18 | 19 | __**Notes:**__ 20 | * if done blindly, the ''known_host''-file may grow very large. It might be wise to check for key existance first 21 | * if multiple keys for the same host exist in ''known_hosts'', the first one is taken (which might be an old or wrong one) 22 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/grouping_subshell.txt: -------------------------------------------------------------------------------- 1 | ====== Grouping commands in a subshell ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | ( ) 6 | 7 | 8 | 9 | ===== Description ===== 10 | The [[syntax:basicgrammar#lists|list]] '''' is executed in a separate shell - a subprocess. No changes to the environment (variables etc...) are reflected in the "main shell". 11 | 12 | ===== Examples ===== 13 | 14 | Execute a command in a different directory. 15 | 16 | echo "$PWD" 17 | ( cd /usr; echo "$PWD" ) 18 | echo "$PWD" # Still in the original directory. 19 | 20 | 21 | ===== Portability considerations ===== 22 | 23 | * The subshell compound command is specified by POSIX. 24 | * Avoid ambiguous syntax. 25 | 26 | (((1+1))) # Equivalent to: (( (1+1) )) 27 | 28 | 29 | ===== See also ===== 30 | * [[syntax:ccmd:grouping_plain | grouping commands]] 31 | * [[http://mywiki.wooledge.org/SubShell | Subshells on Greycat's wiki]] 32 | -------------------------------------------------------------------------------- /docs/dict/globbing.md: -------------------------------------------------------------------------------- 1 | # Globbing 2 | 3 | Globbing is the procedure of 4 | 5 | - matching all filenames against a given pattern 6 | - expanding to all matching filenames 7 | 8 | Unlike MSDOS, where the called program had to interpret the patterns, 9 | the globbing on UNIX(r) is done by the shell, the matched filenames are 10 | given as parameters to a called command: 11 | 12 | $ cat *.txt 13 | 14 | really executes 15 | 16 | $ cat 1.txt 3.txt foobar.txt XXX.txt 17 | 18 | The term \"glob\" originates back in the UNIX(r) days where an 19 | executable `glob` (from \"global\") existed which was used to expand 20 | pattern-matching characters. Later, this functionality was built into 21 | the shell. There's still a library function called `glob()` (POSIX(r)), 22 | which serves the same purpose. 23 | 24 | ## See also 25 | 26 | - [shell](../dict/shell.md) 27 | - [hardlink](../dict/hardlink.md) 28 | 29 | ## See also (article) 30 | 31 | - [pathname expansion](../syntax/expansion/globs.md) 32 | -------------------------------------------------------------------------------- /original_source/user/thebonsai/imprint.txt: -------------------------------------------------------------------------------- 1 | ====== Imprint ====== 2 | 3 | My provider forces me to publish my full and true name and address here. Otherwise they can close and lock the account. **I strictly contradict every unpermitted use of my name and address. Especially sending commercials of your own accord and/or selling the address are strictly forbidden! For exceptions my written permission is absolutely necessary.** 4 | 5 | Responsible for site content and design: 6 | 7 | ''Jan Schampera\\ Erich-Schott-Str. 2\\ 95666 Mitterteich\\ Federal Republic of Germany'' 8 | 9 | 10 | //"I am not responsible for contents of linked pages. I dissociate myself from illegal contents, especially child porn, any radical statements, picture material as well as illegal links. The webmasters of linked pages are responsible by themselves! I assure my users of trying to link only serious pages, and of checking my links first. But at least I can not guarantee for unknown people and their thoughts."// 11 | -------------------------------------------------------------------------------- /docs/snipplets/ssh_fetchkeys.md: -------------------------------------------------------------------------------- 1 | # Fetching SSH hostkeys without interaction 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: ssh, ssh-keys 4 | LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera 5 | 6 | ------------------------------------------------------------------------ 7 | 8 | Applies at least to `openssh`. 9 | 10 | To get the hostkeys for a server, and write them to `known_hosts`-file 11 | (to avoid that yes/no query when the key isn't known), you can do: 12 | 13 | ssh-keyscan -t rsa foo foo.example.com 1.2.3.4 >> ~/.ssh/known_host 14 | 15 | This example queries the hostkeys for the very same machine, but under 3 16 | different \"names\" (hostname, FQDN, IP) and redirects the output to the 17 | `known_hosts`-file. 18 | 19 | **Notes:** 20 | 21 | - if done blindly, the `known_host`-file may grow very large. It might 22 | be wise to check for key existance first 23 | - if multiple keys for the same host exist in `known_hosts`, the first 24 | one is taken (which might be an old or wrong one) 25 | -------------------------------------------------------------------------------- /original_source/dict/terms/globbing.txt: -------------------------------------------------------------------------------- 1 | ====== Globbing ====== 2 | 3 | Globbing is the procedure of 4 | * matching all filenames against a given pattern 5 | * expanding to all matching filenames 6 | 7 | Unlike MSDOS, where the called program had to interpret the patterns, the globbing on UNIX(r) is done by the shell, the matched filenames are given as parameters to a called command: 8 | 9 | $ cat *.txt 10 | 11 | really executes 12 | 13 | $ cat 1.txt 3.txt foobar.txt XXX.txt 14 | 15 | 16 | The term "glob" originates back in the UNIX(r) days where an executable ''glob'' (from "global") existed which was used to expand pattern-matching characters. Later, this functionality was built into the shell. There's still a library function called ''glob()'' (POSIX(r)), which serves the same purpose. 17 | 18 | ===== See also ===== 19 | * [[dict:terms:shell | shell]] 20 | * [[dict:terms:hardlink | hardlink]] 21 | 22 | ===== See also (article) ===== 23 | * [[ syntax:expansion:globs | pathname expansion]] 24 | -------------------------------------------------------------------------------- /docs/misc/shell_humor.md: -------------------------------------------------------------------------------- 1 | # Shell Humor 2 | 3 | Nothing special, just my private collection of some more or less funny 4 | shell stuff I saw during the years. 5 | 6 | Usually Bash and/or Linux (GNU Toolset) specific. 7 | 8 | $ %blow 9 | -bash: fg: %blow: no such job 10 | 11 | $ ar m god 12 | ar: creating god 13 | 14 | $ touch /pussy 15 | touch: cannot touch `/pussy': Permission denied 16 | 17 | $ mount; fsck; fsck; fsck; umount; sleep 18 | 19 | # the lover variant 20 | $ unzip; strip; touch; finger; grep; mount; fsck; more; yes; fsck; fsck; umount; sleep 21 | 22 | # it's not directly funny, only because it's not obvious that this is an sed command 23 | # for the <<<, it works only in Bash 24 | $ sed streetlight <<< reeter 25 | lighter 26 | 27 | # see above for comments 28 | $ sed statement <<< cat 29 | cement 30 | 31 | $ (- 32 | bash: (-: command not found 33 | 34 | $ echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc 35 | GET A LIFE! 36 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/arithmetic_eval.md: -------------------------------------------------------------------------------- 1 | # Arithmetic evaluation (command) 2 | 3 | ## Synopsis 4 | 5 | (( )) 6 | 7 | ## Description 8 | 9 | This command evaluates the [arithmetic expression](../../syntax/arith_expr.md) 10 | ``. 11 | 12 | If the expression evaluates to 0 then the exit code of the expression is 13 | set to 1 (`FALSE`). If the expression evaluates to something else than 14 | 0, then the exit code of the expression is set to 0 (`TRUE`). For this 15 | return code mapping, please see [this 16 | section](../../syntax/arith_expr.md#arithmetic_expressions_and_return_codes). 17 | 18 | The functionality basically is equivalent to what the [`let` builtin 19 | command](../../commands/builtin/let.md) does. The arithmetic evaluation compound 20 | command should be preferred. 21 | 22 | ## Examples 23 | 24 | ## Portability considerations 25 | 26 | ## See also 27 | 28 | - Internal: [arithmetic expressions](../../syntax/arith_expr.md) 29 | - Internal: [arithmetic expansion](../../syntax/expansion/arith.md) 30 | - Internal: [The `let` builtin command](../../commands/builtin/let.md) 31 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/arithmetic_eval.txt: -------------------------------------------------------------------------------- 1 | ====== Arithmetic evaluation (command) ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | (( )) 6 | 7 | 8 | ===== Description ===== 9 | This command evaluates the [[syntax:arith_expr | arithmetic expression]] ''''. 10 | 11 | If the expression evaluates to 0 then the exit code of the expression is set to 1 (''FALSE''). If the expression evaluates to something else than 0, then the exit code of the expression is set to 0 (''TRUE''). For this return code mapping, please see [[syntax:arith_expr#arithmetic_expressions_and_return_codes | this section]]. 12 | 13 | 14 | The functionality basically is equivalent to what the [[commands:builtin:let | ''let'' builtin command]] does. The arithmetic evaluation compound command should be preferred. 15 | 16 | ===== Examples ===== 17 | 18 | 19 | ===== Portability considerations ===== 20 | 21 | ===== See also ===== 22 | * Internal: [[syntax:arith_expr | arithmetic expressions]] 23 | * Internal: [[syntax:expansion:arith | arithmetic expansion]] 24 | * Internal: [[commands:builtin:let | The ''let'' builtin command]] 25 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/until_loop.md: -------------------------------------------------------------------------------- 1 | # The until loop 2 | 3 | ## Synopsis 4 | 5 | until ; do 6 | 7 | done 8 | 9 | ## Description 10 | 11 | The until-loop is relatively simple in what it does: it executes the 12 | [command list](../../syntax/basicgrammar.md#lists) `` and if the exit 13 | code of it was **not** 0 (FALSE) it executes ``. This happens 14 | again and again until `` returns TRUE. 15 | 16 | This is exactly the opposite of the [while 17 | loop](../../syntax/ccmd/while_loop.md). 18 | 19 | :!: Like all loops (both `for`-loops, `while` and `until`), this loop 20 | can be 21 | 22 | - terminated (broken) by the `break` command, optionally as `break N` 23 | to break `N` levels of nested loops 24 | - forced to immediately do the next iteration using the `continue` 25 | command, optionally as `continue N` analog to `break N` 26 | 27 | ### Return status 28 | 29 | The return status is the one of the last command executed in ``, 30 | or `0` (`TRUE`) if none was executed. 31 | 32 | ## Examples 33 | 34 | ## Portability considerations 35 | 36 | ## See also 37 | 38 | - Internal: [The while loop](../../syntax/ccmd/while_loop.md) 39 | -------------------------------------------------------------------------------- /original_source/misc/shell_humor.txt: -------------------------------------------------------------------------------- 1 | ====== Shell Humor ====== 2 | 3 | Nothing special, just my private collection of some more or less funny shell stuff I saw during the years. 4 | 5 | Usually Bash and/or Linux (GNU Toolset) specific. 6 | 7 | 8 | $ %blow 9 | -bash: fg: %blow: no such job 10 | 11 | 12 | 13 | $ ar m god 14 | ar: creating god 15 | 16 | 17 | 18 | $ touch /pussy 19 | touch: cannot touch `/pussy': Permission denied 20 | 21 | 22 | 23 | $ mount; fsck; fsck; fsck; umount; sleep 24 | 25 | 26 | 27 | # the lover variant 28 | $ unzip; strip; touch; finger; grep; mount; fsck; more; yes; fsck; fsck; umount; sleep 29 | 30 | 31 | 32 | # it's not directly funny, only because it's not obvious that this is an sed command 33 | # for the <<<, it works only in Bash 34 | $ sed streetlight <<< reeter 35 | lighter 36 | 37 | 38 | 39 | # see above for comments 40 | $ sed statement <<< cat 41 | cement 42 | 43 | 44 | 45 | $ \(- 46 | bash: (-: command not found 47 | 48 | 49 | 50 | $ echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc 51 | GET A LIFE! 52 | 53 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/until_loop.txt: -------------------------------------------------------------------------------- 1 | ====== The until loop ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | until ; do 6 | 7 | done 8 | 9 | 10 | ===== Description ===== 11 | The until-loop is relatively simple in what it does: it executes the [[syntax:basicgrammar#lists | command list]] '''' and if the exit code of it was **not** 0 (FALSE) it executes ''''. This happens again and again until '''' returns TRUE. 12 | 13 | This is exactly the opposite of the [[syntax:ccmd:while_loop | while loop]]. 14 | 15 | :!: Like all loops (both ''for''-loops, ''while'' and ''until''), this loop can be 16 | * terminated (broken) by the ''break'' command, optionally as ''break N'' to break ''N'' levels of nested loops 17 | * forced to immediately do the next iteration using the ''continue'' command, optionally as ''continue N'' analog to ''break N'' 18 | 19 | ==== Return status ==== 20 | 21 | The return status is the one of the last command executed in '''', or ''0'' (''TRUE'') if none was executed. 22 | 23 | ===== Examples ===== 24 | 25 | ===== Portability considerations ===== 26 | 27 | ===== See also ===== 28 | 29 | * Internal: [[syntax:ccmd:while_loop | The while loop]] 30 | -------------------------------------------------------------------------------- /original_source/dict/terms/interpreter_directive.txt: -------------------------------------------------------------------------------- 1 | ====== Interpreter Directive ====== 2 | 3 | * shebang 4 | 5 | The interpreter directive, usually called shebang, is the character sequence starting with ''#!'' (hash, exclamation-point) at the beginning of the very first line of an executable text file on unixoid operating systems. 6 | 7 | The program loader of the operating system may use this line to load an interpreter for this file when executed. This makes it a self-executable script. 8 | 9 | A shebang will typically look like 10 | 11 | #!/bin/bash 12 | 13 | 14 | Since the line starting with ''#'' is a comment for the shell (and some other scripting languages), it's ignored. 15 | 16 | Regarding the shebang, there are various, differences between operating systems, including: 17 | * may require a space after ''#!'' and before the pathname of the interpreter 18 | * may be able to take arguments for the interpreter 19 | * ... 20 | 21 | POSIX(r) doesn't specify the shebang, though in general it's commonly supported by operating systems. 22 | 23 | ===== See also ===== 24 | * [[http://www.in-ulm.de/~mascheck/various/shebang/ | #!-magic]] - a nice overview of the differences between various operating systems 25 | -------------------------------------------------------------------------------- /docs/dict/interpreter_directive.md: -------------------------------------------------------------------------------- 1 | # Interpreter Directive 2 | 3 | - shebang 4 | 5 | The interpreter directive, usually called shebang, is the character 6 | sequence starting with `#!` (hash, exclamation-point) at the beginning 7 | of the very first line of an executable text file on unixoid operating 8 | systems. 9 | 10 | The program loader of the operating system may use this line to load an 11 | interpreter for this file when executed. This makes it a self-executable 12 | script. 13 | 14 | A shebang will typically look like 15 | 16 | #!/bin/bash 17 | 18 | Since the line starting with `#` is a comment for the shell (and some 19 | other scripting languages), it's ignored. 20 | 21 | Regarding the shebang, there are various, differences between operating 22 | systems, including: 23 | 24 | - may require a space after `#!` and before the pathname of the 25 | interpreter 26 | - may be able to take arguments for the interpreter 27 | - \... 28 | 29 | POSIX(r) doesn't specify the shebang, though in general it's commonly 30 | supported by operating systems. 31 | 32 | ## See also 33 | 34 | - [#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/) - a nice 35 | overview of the differences between various operating systems 36 | -------------------------------------------------------------------------------- /docs/dict/end_of_options.md: -------------------------------------------------------------------------------- 1 | # End of Options 2 | 3 | The options of UNIX(r) utilities usually are introduced with a dash 4 | (`-`) character. 5 | 6 | This is problematic when a non-option argument has to be specified that 7 | begins with a dash. A common example for this are filenames. 8 | 9 | Many utilities use the convention to specify two consecutive dashes 10 | (`--`) to signal \"end of options at this point\". Beyond this tag, no 11 | options are processed anymore, even if an argument begins with a dash. 12 | 13 | Example: You want to list (`ls`) the file with the name `-hello`. With 14 | common option processing, this could end up in the ls-options `-h`, 15 | `-e`, `-l` and `-o` and probably in an error message about invalid 16 | options. You use this to avoid the wrong option processing: 17 | 18 | ls -- -hello 19 | 20 | POSIX(r) specifies that every utility should follow this rule (see ch. 21 | [12.2 Utility Syntax 22 | Guidelines](https://pubs.opengroup.org/onlinepubs/9699919799.2013edition/basedefs/V1_chap12.html)), 23 | except 24 | 25 | - `echo` (historical reasons) 26 | - `test` (obvious parsing reasons) 27 | 28 | ## See also 29 | 30 | - Scripting article, internal: 31 | [getopts_tutorial](../howto/getopts_tutorial.md) 32 | -------------------------------------------------------------------------------- /original_source/dict/terms/end_of_options.txt: -------------------------------------------------------------------------------- 1 | ====== End of Options ====== 2 | 3 | The options of UNIX(r) utilities usually are introduced with a dash (''-'') character. 4 | 5 | This is problematic when a non-option argument has to be specified that begins with a dash. A common example for this are filenames. 6 | 7 | Many utilities use the convention to specify two consecutive dashes (''--'') to signal "end of options at this point". Beyond this tag, no options are processed anymore, even if an argument begins with a dash. 8 | 9 | Example: You want to list (''ls'') the file with the name ''-hello''. With common option processing, this could end up in the ls-options ''-h'', ''-e'', ''-l'' and ''-o'' and probably in an error message about invalid options. You use this to avoid the wrong option processing: 10 | 11 | ls -- -hello 12 | 13 | 14 | POSIX(r) specifies that every utility should follow this rule (see ch. [[https://pubs.opengroup.org/onlinepubs/9699919799.2013edition/basedefs/V1_chap12.html|12.2 Utility Syntax Guidelines]]), except 15 | * ''echo'' (historical reasons) 16 | * ''test'' (obvious parsing reasons) 17 | 18 | ===== See also ===== 19 | 20 | * Scripting article, internal: [[howto:getopts_tutorial]] 21 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/intro.txt: -------------------------------------------------------------------------------- 1 | ====== Bash compound commands ====== 2 | 3 | The main part of Bash's syntax are the so-called **compound commands**. They're called like that because they use "real" commands ([[syntax:basicgrammar#simple_commands | simple commands]] or [[syntax:basicgrammar#lists | lists]]) and knit some intelligence around them. That is what the essential "Bash language" is made of. 4 | 5 | ===== Command grouping ===== 6 | * grouping: [[grouping_plain | command grouping]] 7 | * grouping again: [[grouping_subshell | command grouping in a subshell]] 8 | 9 | 10 | ===== Conditional reactions ===== 11 | 12 | Note that conditionals can also be scripted using [[syntax:basicgrammar#lists | list]], which are syntax elements, not commands. 13 | 14 | * the "new" test command: [[conditional_expression | conditional expression]] 15 | * if-clause: [[if_clause | conditional branching]] 16 | * case statement: [[case | pattern-based branching]] 17 | 18 | ===== Loops ===== 19 | * [[classic_for | classic for-loop]] 20 | * [[c_for | C-style for-loop]] 21 | * [[while_loop | while loop]] 22 | * [[until_loop | until loop]] 23 | 24 | ===== Misc ===== 25 | * math: [[arithmetic_eval | arithmetic evaluation]] 26 | * menus: [[user_select | user selections]] -------------------------------------------------------------------------------- /docs/syntax/ccmd/intro.md: -------------------------------------------------------------------------------- 1 | # Bash compound commands 2 | 3 | The main part of Bash's syntax are the so-called **compound commands**. 4 | They're called like that because they use "real" commands ([simple 5 | commands](../../syntax/basicgrammar.md#simple_commands) or 6 | [lists](../../syntax/basicgrammar.md#lists)) and knit some intelligence around 7 | them. That is what the essential "Bash language" is made of. 8 | 9 | ## Command grouping 10 | 11 | - grouping: [command grouping](grouping_plain.md) 12 | - grouping again: [command grouping in a subshell](grouping_subshell.md) 13 | 14 | ## Conditional reactions 15 | 16 | Note that conditionals can also be scripted using 17 | [list](../../syntax/basicgrammar.md#lists), which are syntax elements, not 18 | commands. 19 | 20 | - the "new" test command: [conditional 21 | expression](conditional_expression.md) 22 | - if-clause: [conditional branching](if_clause.md) 23 | - case statement: [pattern-based branching](case.md) 24 | 25 | ## Loops 26 | 27 | - [classic for-loop](classic_for.md) 28 | - [C-style for-loop](c_for.md) 29 | - [while loop](while_loop.md) 30 | - [until loop](until_loop.md) 31 | 32 | ## Misc 33 | 34 | - math: [arithmetic evaluation](arithmetic_eval.md) 35 | - menus: [user selections](user_select.md) 36 | -------------------------------------------------------------------------------- /docs/commands/builtin/exit.md: -------------------------------------------------------------------------------- 1 | # The exit builtin command 2 | 3 | ## Synopsis 4 | 5 | exit [N] 6 | 7 | ## Description 8 | 9 | The `exit` command terminates the current shell (or script). 10 | 11 | If `N` is given, the return code to the parent process is set to `N`. If 12 | not, the returned status the the status of the most recently executed 13 | command (i.e. `$?`). 14 | 15 | A [trap](../../commands/builtin/trap.md) on `EXIT` is executed before the shell 16 | exits, except the executed `exit` command is part of an already running 17 | trap. 18 | 19 | ### Options 20 | 21 | There are no options. 22 | 23 | ### Exit status 24 | 25 | Naturally, you can't ask for the exit status from within the shell that 26 | executed the `exit` command, because the shell exits. 27 | 28 | |Status|Reason| 29 | |------|------| 30 | |255|invalid (e.g. non-numeric) argument - this staus is returned to the parent| 31 | 32 | ## Examples 33 | 34 | ### Exit the shell and explicitely set its exit status 35 | 36 | exit 3 37 | 38 | ## Portability considerations 39 | 40 | - if `N` is specified, but its value is not between 0 and 255 41 | inclusively, the exit status is undefined. 42 | 43 | ## See also 44 | 45 | - [The trap builtin command](../../commands/builtin/trap.md) 46 | - [The exit status](../../dict/exit_status.md) 47 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/while_loop.md: -------------------------------------------------------------------------------- 1 | # The while-loop 2 | 3 | ## Synopsis 4 | 5 | while ; do 6 | 7 | done 8 | 9 | ## Description 10 | 11 | The while-loop is relatively simple in what it does: it executes the 12 | [command list](../../syntax/basicgrammar.md#lists) `` and if the exit 13 | code of it was 0 (TRUE) it executes ``. This happens again and 14 | again until `` returns FALSE. 15 | 16 | This is exactly the opposite of the [until 17 | loop](../../syntax/ccmd/until_loop.md). 18 | 19 | :!: Like all loops (both `for`-loops, `while` and `until`), this loop 20 | can be 21 | 22 | - terminated (broken) by the `break` command, optionally as `break N` 23 | to break `N` levels of nested loops 24 | - forced to immediately do the next iteration using the `continue` 25 | command, optionally as `continue N` analog to `break N` 26 | 27 | ### Return status 28 | 29 | The return status is the one of the last command executed in ``, 30 | or `0` (`TRUE`) if none was executed. 31 | 32 | ## Examples 33 | 34 | ## Portability considerations 35 | 36 | ## See also 37 | 38 | - Internal: [The until loop](../../syntax/ccmd/until_loop.md) 39 | - Internal: [code examples of the read builtin 40 | command](../../commands/builtin/read.md#code_examples) to see how you can 41 | loop over lines 42 | -------------------------------------------------------------------------------- /docs/commands/builtin/readonly.md: -------------------------------------------------------------------------------- 1 | # The readonly builtin command 2 | 3 | ## Synopsis 4 | 5 | readonly [-p] [-a] [-A] [-f] [NAME[=VALUE] ...] 6 | 7 | ## Description 8 | 9 | The `readonly` builtin command is used to mark variables or functions as 10 | read-only, which means unchangeable. This implies that it can't be 11 | unset anymore. A `readonly` variable may not be redefined in child 12 | scopes. A readonly global may not be redefined as a function local 13 | variable. Simple command environment assignments may not reference 14 | readonly variables. 15 | 16 | ### Options 17 | 18 | |Option|Description| 19 | |-|-| 20 | |`-a`|refer to normal arrays| 21 | |`-A`|refer to associative arrays| 22 | |`-f`|refer to functions| 23 | |`-p`|print all read-only variables or functions, `-a`, `-A` and `-f` can be used to filter. The output is reusable as input| 24 | 25 | An argument of `--` disables further option processing. 26 | 27 | ### Return status 28 | 29 | |Status|Reason| 30 | |-|-| 31 | |0|no error| 32 | |!=0|invalid option| 33 | |!=0|invalid combination of options| 34 | |!=0|a given `NAME` is invalid| 35 | 36 | ## Examples 37 | 38 | ## Portability considerations 39 | 40 | - in POSIX(r), only the `-p` option is specified 41 | 42 | ## See also 43 | 44 | - [declare](../../commands/builtin/declare.md) 45 | - [unset](../../commands/builtin/unset.md) 46 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/while_loop.txt: -------------------------------------------------------------------------------- 1 | ====== The while-loop ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | while ; do 6 | 7 | done 8 | 9 | 10 | ===== Description ===== 11 | The while-loop is relatively simple in what it does: it executes the [[syntax:basicgrammar#lists | command list]] '''' and if the exit code of it was 0 (TRUE) it executes ''''. This happens again and again until '''' returns FALSE. 12 | 13 | This is exactly the opposite of the [[syntax:ccmd:until_loop | until loop]]. 14 | 15 | :!: Like all loops (both ''for''-loops, ''while'' and ''until''), this loop can be 16 | * terminated (broken) by the ''break'' command, optionally as ''break N'' to break ''N'' levels of nested loops 17 | * forced to immediately do the next iteration using the ''continue'' command, optionally as ''continue N'' analog to ''break N'' 18 | 19 | ==== Return status ==== 20 | 21 | The return status is the one of the last command executed in '''', or ''0'' (''TRUE'') if none was executed. 22 | 23 | ===== Examples ===== 24 | 25 | 26 | ===== Portability considerations ===== 27 | 28 | 29 | ===== See also ===== 30 | 31 | * Internal: [[syntax:ccmd:until_loop | The until loop]] 32 | * Internal: [[commands:builtin:read#code_examples|code examples of the read builtin command]] to see how you can loop over lines 33 | -------------------------------------------------------------------------------- /original_source/commands/builtin/exit.txt: -------------------------------------------------------------------------------- 1 | ====== The exit builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | exit [N] 5 | 6 | ===== Description ===== 7 | The ''exit'' command terminates the current shell (or script). 8 | 9 | If ''N'' is given, the return code to the parent process is set to ''N''. If not, the returned status the the status of the most recently executed command (i.e. ''$?''). 10 | 11 | A [[commands:builtin:trap|trap]] on ''EXIT'' is executed before the shell exits, except the executed ''exit'' command is part of an already running trap. 12 | 13 | ==== Options ==== 14 | There are no options. 15 | 16 | 17 | ==== Exit status ==== 18 | 19 | Naturally, you can't ask for the exit status from within the shell that executed the ''exit'' command, because the shell exits. 20 | 21 | ^Status ^Reason ^ 22 | |255 |invalid (e.g. non-numeric) argument - this staus is returned to the parent | 23 | 24 | 25 | ===== Examples ===== 26 | 27 | ==== Exit the shell and explicitely set its exit status ==== 28 | 29 | exit 3 30 | 31 | 32 | ===== Portability considerations ===== 33 | * if ''N'' is specified, but its value is not between 0 and 255 inclusively, the exit status is undefined. 34 | 35 | 36 | ===== See also ===== 37 | * [[commands:builtin:trap|The trap builtin command]] 38 | * [[dict:terms:exit_status|The exit status]] 39 | 40 | -------------------------------------------------------------------------------- /original_source/commands/builtin/readonly.txt: -------------------------------------------------------------------------------- 1 | ====== The readonly builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | 6 | readonly [-p] [-a] [-A] [-f] [NAME[=VALUE] ...] 7 | 8 | 9 | ===== Description ===== 10 | 11 | The ''readonly'' builtin command is used to mark variables or functions as read-only, which means unchangeable. This implies that it can't be unset anymore. A ''readonly'' variable may not be redefined in child scopes. A readonly global may not be redefined as a function local variable. Simple command environment assignments may not reference readonly variables. 12 | 13 | ==== Options ==== 14 | 15 | ^Option ^Description ^ 16 | |''-a'' |refer to normal arrays | 17 | |''-A'' |refer to associative arrays | 18 | |''-f'' |refer to functions | 19 | |''-p'' |print all read-only variables or functions, ''-a'', ''-A'' and ''-f'' can be used to filter. The output is reusable as input | 20 | 21 | An argument of ''%%--%%'' disables further option processing. 22 | ==== Return status ==== 23 | 24 | ^Status ^Reason ^ 25 | |0 |no error | 26 | |!=0 |invalid option | 27 | |!=0 |invalid combination of options | 28 | |!=0 |a given ''NAME'' is invalid | 29 | 30 | ===== Examples ===== 31 | 32 | ===== Portability considerations ===== 33 | 34 | * in POSIX(r), only the ''-p'' option is specified 35 | 36 | ===== See also ===== 37 | 38 | * [[commands:builtin:declare]] 39 | * [[commands:builtin:unset]] -------------------------------------------------------------------------------- /docs/commands/builtin/export.md: -------------------------------------------------------------------------------- 1 | # The export builtin command 2 | 3 | ## Synopsis 4 | 5 | export [-fn] [NAME[=VALUE] ...] 6 | export -p 7 | 8 | ## Description 9 | 10 | The `export` builtin command is used to mark variables or functions 11 | referenced by `NAME` for automatic export to the environment. If `NAME` 12 | is a shell variable, a value `VALUE` can be assigned before exporting 13 | it. 14 | 15 | ### Options 16 | 17 | |Option|Description| 18 | |------|-----------| 19 | |`-f`|refer to shell functions| 20 | |`-n`|remove the export property from any referenced `NAME`| 21 | |`-p`|print all exported variables, with `-f`, print all exported functions - all in a format re-usable as input| 22 | 23 | An argument of `--` disables further option processing. 24 | 25 | ### Return status 26 | 27 | |Status|Reason| 28 | |------|------| 29 | |0|no error| 30 | |!=0|invalid option| 31 | |!=0|a given `NAME` is invalid| 32 | 33 | ## Examples 34 | 35 | Set the display to use when launching a GUI application (useful during 36 | SSH sessions): 37 | 38 | export DISPLAY=":0" 39 | 40 | Set your default text editor (e.g. SublimeText): 41 | 42 | export EDITOR=subl 43 | 44 | ## Portability considerations 45 | 46 | - in POSIX(r), only the `-p` option is specified 47 | - in POSIX(r), only variables (with value assignment) are to be 48 | exported, not shell functions 49 | 50 | ## See also 51 | 52 | - [declare](../../commands/builtin/declare.md) 53 | -------------------------------------------------------------------------------- /original_source/snipplets/xclip.txt: -------------------------------------------------------------------------------- 1 | ====== X-Clipboard on Commandline ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: clipboard, x11, xclip, readline 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Josh Triplett 7 | type: snipplet 8 | ---- 9 | 10 | 11 | # Make Control-v paste, if in X and if xclip available - Josh Triplett 12 | if [ -n "$DISPLAY" ] && [ -x /usr/bin/xclip ] ; then 13 | # Work around a bash bug: \C-@ does not work in a key binding 14 | bind '"\C-x\C-m": set-mark' 15 | # The '#' characters ensure that kill commands have text to work on; if 16 | # not, this binding would malfunction at the start or end of a line. 17 | bind 'Control-v: "#\C-b\C-k#\C-x\C-?\"$(xclip -o -selection c)\"\e\C-e\C-x\C-m\C-a\C-y\C-?\C-e\C-y\ey\C-x\C-x\C-d"' 18 | fi 19 | 20 | 21 | The behaviour is a bit tricky to explain: 22 | * kill text after the cursor 23 | * since the kill command **wants** text, it blindly adds a fake text "#" here 24 | * kill text before the cursor 25 | * since the kill command **wants** text, it blindly adds a fake text "#" here, too 26 | * write out ''"$(xclip -o -selection c)"'' 27 | * run Control-Meta-e (shell-expand-line) to expand the ''"$(xclip -o -selection c)"'' 28 | * yank the previously killed text back where it belongs 29 | 30 | Of course you can use any other command, you're not limited to ''xclip'' here. 31 | 32 | Note: C-@ as well as M-SPC both works and set the mark for me -- pgas 33 | -------------------------------------------------------------------------------- /docs/commands/builtin/wait.md: -------------------------------------------------------------------------------- 1 | # The wait builtin command 2 | 3 | ## Synopsis 4 | 5 | wait [-f] [-n] [-p VARNAME] [ID...] 6 | 7 | ## Description 8 | 9 | The `wait` builtin command is used to wait for job completion and return 10 | exit status. 11 | 12 | - if `ID` is a job specification, it waits for all processes in the 13 | pipeline of this job 14 | - waits for a specific job (asynchronous command) and report its exit 15 | status if one or more `ID` is given 16 | - waits for all running jobs (asynchronous commands) 17 | - waits for "the next" job (`-n` option) 18 | - waits for termination instead of status change (`-f` option) 19 | 20 | `ID` may be an operating system process identifier or a shell job 21 | specification. 22 | 23 | ### Options 24 | 25 | |Option|Description| 26 | |------|-----------| 27 | |`-n`|Waits for "the next" child to exit (as opposed to "all children" without this option). Accepts a list of IDs (jobs)| 28 | |`-f`|Waits for the termination of the given `ID` (instead of waiting for a status change only)| 29 | |`-p VARNAME`|When waiting for a list (-n) or all jobs, writes the job ID to the job that was actually terminated into the variable `VARNAME`| 30 | 31 | ### Return status 32 | 33 | The return status is the return status of the job waited for, or 34 | 35 | |Status|Reason| 36 | |------|------| 37 | |0|waited for all jobs in shell's job list| 38 | |1|the given `ID` is not a valid job or process ID| 39 | 40 | ## Examples 41 | 42 | ## Portability considerations 43 | 44 | ## See also 45 | -------------------------------------------------------------------------------- /original_source/commands/builtin/export.txt: -------------------------------------------------------------------------------- 1 | ====== The export builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | 6 | export [-fn] [NAME[=VALUE] ...] 7 | export -p 8 | 9 | 10 | ===== Description ===== 11 | 12 | The ''export'' builtin command is used to mark variables or functions referenced by ''NAME'' for automatic export to the environment. If ''NAME'' is a shell variable, a value ''VALUE'' can be assigned before exporting it. 13 | 14 | ==== Options ==== 15 | 16 | ^Option ^Description ^ 17 | |''-f'' |refer to shell functions | 18 | |''-n'' |remove the export property from any referenced ''NAME'' | 19 | |''-p'' |print all exported variables, with ''-f'', print all exported functions - all in a format re-usable as input | 20 | 21 | An argument of ''%%--%%'' disables further option processing. 22 | ==== Return status ==== 23 | 24 | ^Status ^Reason ^ 25 | |0 |no error | 26 | |!=0 |invalid option | 27 | |!=0 |a given ''NAME'' is invalid | 28 | 29 | ===== Examples ===== 30 | 31 | Set the display to use when launching a GUI application (useful during SSH sessions): 32 | 33 | export DISPLAY=":0" 34 | 35 | 36 | Set your default text editor (e.g. SublimeText): 37 | 38 | export EDITOR=subl 39 | 40 | ===== Portability considerations ===== 41 | 42 | * in POSIX(r), only the ''-p'' option is specified 43 | * in POSIX(r), only variables (with value assignment) are to be exported, not shell functions 44 | 45 | ===== See also ===== 46 | 47 | * [[commands:builtin:declare]] 48 | -------------------------------------------------------------------------------- /docs/snipplets/xclip.md: -------------------------------------------------------------------------------- 1 | # X-Clipboard on Commandline 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: clipboard, x11, xclip, 4 | readline LastUpdate_dt: 2010-07-31 Contributors: Josh Triplett type: 5 | snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | # Make Control-v paste, if in X and if xclip available - Josh Triplett 10 | if [ -n "$DISPLAY" ] && [ -x /usr/bin/xclip ] ; then 11 | # Work around a bash bug: \C-@ does not work in a key binding 12 | bind '"\C-x\C-m": set-mark' 13 | # The '#' characters ensure that kill commands have text to work on; if 14 | # not, this binding would malfunction at the start or end of a line. 15 | bind 'Control-v: "#\C-b\C-k#\C-x\C-?\"$(xclip -o -selection c)\"\e\C-e\C-x\C-m\C-a\C-y\C-?\C-e\C-y\ey\C-x\C-x\C-d"' 16 | fi 17 | 18 | The behaviour is a bit tricky to explain: 19 | 20 | - kill text after the cursor 21 | - since the kill command **wants** text, it blindly adds a fake 22 | text \"#\" here 23 | - kill text before the cursor 24 | - since the kill command **wants** text, it blindly adds a fake 25 | text \"#\" here, too 26 | - write out `"$(xclip -o -selection c)"` 27 | - run Control-Meta-e (shell-expand-line) to expand the 28 | `"$(xclip -o -selection c)"` 29 | - yank the previously killed text back where it belongs 30 | 31 | Of course you can use any other command, you\'re not limited to `xclip` 32 | here. 33 | 34 | Note: C-@ as well as M-SPC both works and set the mark for me -- pgas 35 | -------------------------------------------------------------------------------- /docs/snipplets/awkcsv.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - awk 4 | - csv 5 | --- 6 | 7 | # Using `awk` to deal with CSV that uses quoted/unquoted delimiters 8 | 9 | CSV files are a mess, yes. 10 | 11 | Assume you have CSV files that use the comma as delimiter and quoted 12 | data fields that can contain the delimiter. 13 | 14 | "first", "second", "last" 15 | "fir,st", "second", "last" 16 | "firtst one", "sec,ond field", "final,ly" 17 | 18 | Simply using the comma as separator for `awk` won't work here, of 19 | course. 20 | 21 | Solution: Use the field separator `", "|^"|"$` for `awk`. 22 | 23 | This is an OR-ed list of 3 possible separators: 24 | 25 | | | | 26 | |--------|----------------------------------------------| 27 | |`", "` | matches the area between the datafields| 28 | |`^"` | matches the area left of the first datafield| 29 | |`"$` | matches the area right of the last data field| 30 | 31 | You can tune these delimiters if you have other needs (for example if 32 | you don't have a space after the commas). 33 | 34 | Test: 35 | 36 | The `awk` command used for the CSV above just prints the fileds 37 | separated by `###` to see what's going on: 38 | 39 | $ awk -v FS='", "|^"|"$' '{print $2"###"$3"###"$4}' data.csv 40 | first###second###last 41 | fir,st###second###last 42 | firtst one###sec,ond field###final,ly 43 | 44 | **ATTENTION** If the CSV data changes its format every now and then (for 45 | example it only quotes the data fields if needed, not always), then this 46 | way will not work. 47 | -------------------------------------------------------------------------------- /original_source/snipplets/awkcsv.txt: -------------------------------------------------------------------------------- 1 | ====== Using ''awk'' to deal with CSV that uses quoted/unquoted delimiters ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags : awk, csv 5 | LastUpdate_dt : 2010-07-31 6 | Contributors : SiegX (IRC) 7 | type : snipplet 8 | ---- 9 | 10 | CSV files are a mess, yes. 11 | 12 | Assume you have CSV files that use the comma as delimiter and quoted data fields that can contain the delimiter. 13 | 14 | 15 | "first", "second", "last" 16 | "fir,st", "second", "last" 17 | "firtst one", "sec,ond field", "final,ly" 18 | 19 | 20 | Simply using the comma as separator for ''awk'' won't work here, of course. 21 | 22 | Solution: 23 | Use the field separator ''", "|^"|"$'' for ''awk''. 24 | 25 | This is an OR-ed list of 3 possible separators: 26 | |''", "''|matches the area between the datafields| 27 | |''^"''|matches the area left of the first datafield| 28 | |''"$''|matches the area right of the last data field| 29 | 30 | You can tune these delimiters if you have other needs (for example if you don't have a space after the commas). 31 | 32 | Test: 33 | 34 | The ''awk'' command used for the CSV above just prints the fileds separated by ''###'' to see what's going on: 35 | 36 | $ awk -v FS='", "|^"|"$' '{print $2"###"$3"###"$4}' data.csv 37 | first###second###last 38 | fir,st###second###last 39 | firtst one###sec,ond field###final,ly 40 | 41 | 42 | **ATTENTION** If the CSV data changes its format every now and then (for example it only quotes the data fields if needed, not always), then this way will not work. 43 | -------------------------------------------------------------------------------- /docs/dict/hardlink.md: -------------------------------------------------------------------------------- 1 | # Hardlink 2 | 3 | Also the article for: 4 | 5 | - filename 6 | 7 | A hardlink associates a *filename* with a [file](../dict/file.md). That 8 | name is an entry in a directory listing. Of course a file can have more 9 | hardlinks to it (usually the number of hardlinks to a file is limited), 10 | but all hardlinks to a file must reside on the same 11 | `filesystem` as the file itself! 12 | 13 | What you usually call a file is just a name for that file, and thus, a 14 | hardlink. 15 | 16 | The difference between a [symbolic link](../dict/symlink.md) and a hard 17 | link is that there is no easy way to differentiate between a \'real\' 18 | file and a hard link, let's take a look at the example: 19 | 20 | \* create an empty file 21 | 22 | $ touch a 23 | 24 | \* create a hard link \'b\' and sym link \'c\' to empty file 25 | 26 | $ ln a b 27 | $ ln -s a c 28 | 29 | as you can see file(1) can't differentiate between a real file \'a\' 30 | and a hard link \'b\', but it can tell \'c\' is a sym link 31 | 32 | $ file * 33 | a: empty 34 | b: empty 35 | c: symbolic link to `a' 36 | 37 | `ls -i` prints out the inode numbers of files, if two files have the 38 | same inode number AND are on the same file system it means they are 39 | **hardlinked**. 40 | 41 | $ ls -i * 42 | 5262 a 5262 b 5263 c 43 | 44 | hard links don't consume additional space on the filesystem, the space 45 | is freed when the last hard link pointing to it is deleted. 46 | 47 | ## See also 48 | 49 | - [file](../dict/file.md) 50 | - [symlink](../dict/symlink.md) 51 | -------------------------------------------------------------------------------- /original_source/dict/terms/hardlink.txt: -------------------------------------------------------------------------------- 1 | ====== Hardlink ====== 2 | 3 | Also the article for: 4 | * filename 5 | 6 | A hardlink associates a //filename// with a [[dict:terms:file | file]]. That name is an entry in a directory listing. Of course a file can have more hardlinks to it (usually the number of hardlinks to a file is limited), but all hardlinks to a file must reside on the same [[dict:terms:filesystem | filesystem]] as the file itself! 7 | 8 | What you usually call a file is just a name for that file, and thus, a hardlink. 9 | 10 | The difference between a [[dict:terms:symlink | symbolic link]] and a hard link is that there is no easy way to differentiate between a 'real' file and a hard link, let's take a look at the example: 11 | 12 | * create an empty file 13 | 14 | $ touch a 15 | 16 | * create a hard link 'b' and sym link 'c' to empty file 17 | 18 | $ ln a b 19 | $ ln -s a c 20 | 21 | as you can see file(1) can't differentiate between a real file 'a' and a hard link 'b', but it can tell 'c' is a sym link 22 | 23 | $ file * 24 | a: empty 25 | b: empty 26 | c: symbolic link to `a' 27 | 28 | ''ls -i'' prints out the inode numbers of files, if two files have the same inode number AND are on the same file system it means they are **hardlinked**. 29 | 30 | $ ls -i * 31 | 5262 a 5262 b 5263 c 32 | 33 | 34 | hard links don't consume additional space on the filesystem, the space is freed when the last hard link pointing to it is deleted. 35 | 36 | ===== See also ===== 37 | * [[dict:terms:file | file]] 38 | * [[dict:terms:filesystem | filesystem]] 39 | * [[dict:terms:symlink | symlink]] 40 | 41 | -------------------------------------------------------------------------------- /original_source/snipplets/prargs.txt: -------------------------------------------------------------------------------- 1 | ====== Print argument list for testing ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: debug, arguments 5 | LastUpdate_dt: 2013-03-23 6 | Contributors: Snappy (IRC), Dan Douglas 7 | type: snipplet 8 | ---- 9 | 10 | Sometimes you might find it useful to see how arguments passed to a program arrive there. 11 | 12 | Check this script (save it as script file or make a function): 13 | 14 | printf '"%b"\n' "$0" "$@" | nl -v0 -s": " 15 | 16 | 17 | It uses the [[commands:builtin:printf | printf command]] to generate a list of arguments, even with escape sequences interpreted. This list is shown formatted by the nl(1) utility. 18 | 19 | Another alternative with colorized output. If run in Bash, it temporarily disables all debug output for itself, including the test that determines whether to hide debug output. In ksh, tracing would have to be enabled on the function to show debug output, so it works out to being equivalent. 20 | 21 | 22 | # Bash or ksh93 debugging function for colored display of argv. 23 | # Optionally set OFD to the desired output file descriptor. 24 | function args { 25 | { BASH_XTRACEFD=3 command eval ${BASH_VERSION+"$(/dev/null 26 | case $- in *x*) 27 | set +x 28 | trap 'trap RETURN; set -x' RETURN 29 | esac 30 | EOF 31 | 32 | [[ ${OFD-1} == +([0-9]) ]] || return 33 | 34 | if [[ -t ${OFD:-2} ]]; then 35 | typeset -A clr=([green]=$(tput setaf 2) [sgr0]=$(tput sgr0)) 36 | else 37 | typeset clr 38 | fi 39 | 40 | if ! ${1+false}; then 41 | printf -- "${clr[green]}<${clr[sgr0]}%s${clr[green]}>${clr[sgr0]} " "$@" 42 | echo 43 | else 44 | echo 'no args.' 45 | fi >&"${OFD:-2}" 46 | } 47 | -------------------------------------------------------------------------------- /original_source/commands/builtin/wait.txt: -------------------------------------------------------------------------------- 1 | ====== The wait builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | wait [-f] [-n] [-p VARNAME] [ID...] 5 | 6 | ===== Description ===== 7 | The ''wait'' builtin command is used to wait for job completion and return exit status. 8 | 9 | * if ''ID'' is a job specification, it waits for all processes in the pipeline of this job 10 | * waits for a specific job (asynchronous command) and report its exit status if one or more ''ID'' is given 11 | * waits for all running jobs (asynchronous commands) 12 | * waits for "the next" job (''-n'' option) 13 | * waits for termination instead of status change (''-f'' option) 14 | 15 | ''ID'' may be an operating system process identifier or a shell job specification. 16 | 17 | ==== Options ==== 18 | 19 | ^ Option ^ Description ^ 20 | | ''-n'' | Waits for "the next" child to exit (as opposed to "all children" without this option). Accepts a list of IDs (jobs) | 21 | | ''-f'' | Waits for the termination of the given ''ID'' (instead of waiting for a status change only) | 22 | | ''-p VARNAME'' | When waiting for a list (-n) or all jobs, writes the job ID to the job that was actually terminated into the variable ''VARNAME'' | 23 | 24 | ==== Return status ==== 25 | 26 | The return status is the return status of the job waited for, or 27 | 28 | ^Status ^Reason ^ 29 | |0 |waited for all jobs in shell's job list | 30 | |1 |the given ''ID'' is not a valid job or process ID | 31 | 32 | ===== Examples ===== 33 | 34 | 35 | ===== Portability considerations ===== 36 | 37 | 38 | ===== See also ===== 39 | 40 | -------------------------------------------------------------------------------- /original_source/snipplets/largestfile.txt: -------------------------------------------------------------------------------- 1 | ====== Get largest file ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: directory, recursive, find, crawl 5 | LastUpdate_dt: 2013-03-23 6 | Contributors: Dan Douglas 7 | type: snipplet 8 | ---- 9 | 10 | One basic pattern for recursive directory traversal with operations on files at each node. This gets the largest file in each subdirectory. Toggling some small details will make it return the smallest, or traverse breadth-first instead of depth-first. 11 | 12 | 13 | #!/usr/bin/env bash 14 | # GNU find + bash4 / ksh93v / zsh 15 | # Get the largest file matching pattern in the given directories recursively 16 | ${ZSH_VERSION+false} || emulate ksh 17 | ${BASH_VERSION+shopt -s lastpipe extglob} 18 | 19 | function getLargest { 20 | typeset -A cur top || return 21 | typeset dir x 22 | for dir in "$2"/*/; do 23 | [[ -d $dir ]] || return 0 24 | getLargest "$1" "${dir%/}" || return 25 | top[size]=-1 26 | find "$dir" -maxdepth 1 -type f -name "$1" -printf '%s\0%f\0' | { 27 | while :; do 28 | for x in cur\[{size,name}\]; do 29 | IFS= read -rd '' "$x" || break 2 30 | done 31 | if (( cur[size] > top[size] )); then 32 | top[size]=${cur[size]} top[name]=${cur[name]} 33 | fi 34 | done 35 | printf '%q\n' "${dir}${top[name]}" 36 | } 37 | done 38 | } 39 | 40 | # main pattern dir [ dir ... ] 41 | function main { 42 | if [[ -n $1 ]]; then 43 | typeset dir pattern=$1 44 | shift 45 | for dir; do 46 | [[ -d $dir ]] || return 47 | getLargest "$pattern" "$dir" 48 | done 49 | else 50 | return 1 51 | fi 52 | } 53 | 54 | main "$@" 55 | 56 | # vim: set fenc=utf-8 ff=unix ft=sh : 57 | 58 | 59 | ===== More examples ===== 60 | * http://mywiki.wooledge.org/BashFAQ/003 61 | * http://mywiki.wooledge.org/UsingFind -------------------------------------------------------------------------------- /docs/snipplets/prargs.md: -------------------------------------------------------------------------------- 1 | # Print argument list for testing 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: debug, arguments 4 | LastUpdate_dt: 2013-03-23 Contributors: Snappy (IRC), Dan Douglas type: 5 | snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | Sometimes you might find it useful to see how arguments passed to a 10 | program arrive there. 11 | 12 | Check this script (save it as script file or make a function): 13 | 14 | printf '"%b"\n' "$0" "$@" | nl -v0 -s": " 15 | 16 | It uses the [printf command](../commands/builtin/printf.md) to generate a 17 | list of arguments, even with escape sequences interpreted. This list is 18 | shown formatted by the nl(1) utility. 19 | 20 | Another alternative with colorized output. If run in Bash, it 21 | temporarily disables all debug output for itself, including the test 22 | that determines whether to hide debug output. In ksh, tracing would have 23 | to be enabled on the function to show debug output, so it works out to 24 | being equivalent. 25 | 26 | ``` bash 27 | # Bash or ksh93 debugging function for colored display of argv. 28 | # Optionally set OFD to the desired output file descriptor. 29 | function args { 30 | { BASH_XTRACEFD=3 command eval ${BASH_VERSION+"$(/dev/null 31 | case $- in *x*) 32 | set +x 33 | trap 'trap RETURN; set -x' RETURN 34 | esac 35 | EOF 36 | 37 | [[ ${OFD-1} == +([0-9]) ]] || return 38 | 39 | if [[ -t ${OFD:-2} ]]; then 40 | typeset -A clr=([green]=$(tput setaf 2) [sgr0]=$(tput sgr0)) 41 | else 42 | typeset clr 43 | fi 44 | 45 | if ! ${1+false}; then 46 | printf -- "${clr[green]}<${clr[sgr0]}%s${clr[green]}>${clr[sgr0]} " "$@" 47 | echo 48 | else 49 | echo 'no args.' 50 | fi >&"${OFD:-2}" 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /overrides/partials/comments.html: -------------------------------------------------------------------------------- 1 |

{{ lang.t("meta.comments") }}

2 | 3 | 19 | 20 | 21 | 49 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: The Bash Hackers Wiki 2 | site_url: https://flokoe.github.io/bash-hackers-wiki/ 3 | 4 | repo_url: https://github.com/flokoe/bash-hackers-wiki 5 | repo_name: flokoe/bash-hackers-wiki 6 | edit_uri: edit/main/docs/ 7 | 8 | theme: 9 | name: material 10 | custom_dir: overrides 11 | features: 12 | - navigation.instant 13 | - navigation.tracking 14 | - navigation.tabs 15 | - navigation.sections 16 | - navigation.top 17 | - content.action.view 18 | - content.action.edit 19 | - search.suggest 20 | - search.highlight 21 | - content.code.copy 22 | icon: 23 | repo: fontawesome/brands/github 24 | palette: 25 | - scheme: default 26 | toggle: 27 | icon: material/brightness-7 28 | name: Switch to dark mode 29 | - scheme: slate 30 | toggle: 31 | icon: material/brightness-4 32 | name: Switch to light mode 33 | 34 | plugins: 35 | - git-revision-date-localized: 36 | enable_creation_date: true 37 | - search 38 | - awesome-pages 39 | - tags: 40 | tags_file: tags.md 41 | - minify: 42 | minify_html: true 43 | minify_css: true 44 | minify_js: true 45 | htmlmin_opts: 46 | remove_comments: true 47 | cache_safe: true 48 | 49 | markdown_extensions: 50 | - admonition 51 | - pymdownx.emoji: 52 | emoji_index: !!python/name:material.extensions.emoji.twemoji 53 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 54 | - pymdownx.highlight: 55 | anchor_linenums: true 56 | - pymdownx.superfences 57 | - pymdownx.highlight 58 | - pymdownx.inlinehilite 59 | - pymdownx.keys 60 | - pymdownx.smartsymbols 61 | - footnotes 62 | - toc: 63 | permalink: true 64 | 65 | nav: 66 | - Start: index.md 67 | - ... | regex=^(?!need_love\.md|bash4\.md|wishes\.md|tags\.md) 68 | - tags.md 69 | 70 | watch: 71 | - overrides 72 | -------------------------------------------------------------------------------- /docs/commands/builtin/shopt.md: -------------------------------------------------------------------------------- 1 | # The shopt builtin command 2 | 3 | The `shopt` builtin manages [shell options](../../internals/shell_options.md), a 4 | set of boolean (`on`/`off`) configuration variables that control the 5 | behaviour of the shell. 6 | 7 | ## Synopsis 8 | 9 | shopt [-pqsu] [-o] 10 | 11 | ## Description 12 | 13 | Note: Some of these options and other shell options can also be set with 14 | [the set builtin](../../commands/builtin/set.md). 15 | 16 | ### Options 17 | 18 | |Option|Description| 19 | |------|-----------| 20 | |`-o`|Restrict the values of `` to only those also known by [the set builtin](../../commands/builtin/set.md)| 21 | |`-p`|Print all shell options and their current value. **Default**.| 22 | |`-q`|Quiet mode. Set exit code if named option is set. For multiple options: `TRUE` if all options are set, `FALSE` otherwise| 23 | |`-s`|Enable (set) the shell options named by `` or list all *enabled* options if no names are given| 24 | |`-u`|Disabe (unset) the shell options named by `` or list all *disabled* options if no names are given| 25 | 26 | As noted above, if only `-s` or `-u` are given without any option names, 27 | only the currently enabled (`-s`) or disabled (`-u`) options are 28 | printed. 29 | 30 | ### Exit code 31 | 32 | When listing options, the exit code is `TRUE` (0), if all options are 33 | enabled, `FALSE` otherwise. 34 | 35 | When setting/unsetting an option, the exit code is `TRUE` unless the 36 | named option doesn't exitst. 37 | 38 | ## Examples 39 | 40 | Enable the `nullglob` option: 41 | 42 | shopt -s nullglob 43 | 44 | ## Portability considerations 45 | 46 | The `shopt` command is not portable accross different shells. 47 | 48 | ## See also 49 | 50 | - Internal: [The set builtin command](../../commands/builtin/set.md) 51 | - Internal: [List of shell options](../../internals/shell_options.md) 52 | -------------------------------------------------------------------------------- /original_source/syntax/expansion/wordsplit.txt: -------------------------------------------------------------------------------- 1 | ====== Word splitting ====== 2 | 3 | FIXME to be continued! 4 | 5 | Word splitting occurs once any of the following expansions are done (and only then!) 6 | * [[syntax:pe | Parameter expansion]] 7 | * [[syntax:expansion:cmdsubst | Command substitution]] 8 | * [[syntax:expansion:arith | Arithmetic expansion]] 9 | Bash will scan the results of these expansions for special ''IFS'' characters that mark word boundaries. This is only done on results that are **not double-quoted**! 10 | 11 | ===== Internal Field Separator IFS ===== 12 | 13 | The ''IFS'' variable holds the characters that Bash sees as word boundaries in this step. The default contains the characters 14 | * 15 | * 16 | * 17 | These characters are also assumed when IFS is **unset**. When ''IFS'' is **empty** (nullstring), no word splitting is performed at all. 18 | 19 | 20 | 21 | 22 | ===== Behaviour ===== 23 | 24 | The results of the expansions mentioned above are scanned for ''IFS''-characters. If **one or more** (in a sequence) of them is found, the expansion result is split at these positions into multiple words. 25 | 26 | This doesn't happen when the expansion results were **double-quoted**. 27 | 28 | When a null-string (e.g., something that before expanded to >>nothing<<) is found, it is removed, unless it is quoted ('''''' or ''""''). 29 | 30 | __**Again note:**__ Without any expansion beforehand, Bash won't perform word splitting! In this case, the initial token parsing is solely responsible. 31 | 32 | 33 | ===== See also ===== 34 | * [[syntax:expansion:intro | Introduction to expansion and substitution]] 35 | * [[syntax:quoting | Quoting and escaping]] 36 | * [[http://mywiki.wooledge.org/WordSplitting | WordSplitting]], [[http://mywiki.wooledge.org/IFS | IFS]], and [[http://mywiki.wooledge.org/DontReadLinesWithFor | DontReadLinesWithFor]] - Greg's wiki -------------------------------------------------------------------------------- /original_source/commands/builtin/cd.txt: -------------------------------------------------------------------------------- 1 | ====== The cd builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | cd [-L|-P] [DIRECTORY] 5 | cd - 6 | 7 | ===== Description ===== 8 | The ''cd'' builtin command is used to change the current working directory 9 | * to the given directory (''cd DIRECTORY'') 10 | * to the previous working directory (''cd -'') as saved in the [[syntax:shellvars#OLDPWD|OLDPWD]] shell variable 11 | * to the user's home directory as specified in the [[syntax:shellvars#HOME|HOME]] environment variable (when used without a ''DIRECTORY'' argument) 12 | 13 | The ''cd'' builtin command searches the directories listed in [[syntax:shellvars#CDPATH|CDPATH]] for a matching directory. 14 | 15 | The default behaviour is to follow symbolic links unless the ''-P'' option is given or the shell is configured to do so (see the ''-P'' option of [[commands:builtin:set|the set builtin command]]). 16 | 17 | ==== Options ==== 18 | 19 | ^Option^Description^ 20 | |''-L'' |Follow symbolic links (default) | 21 | |''-P'' |Do not follow symbolic links | 22 | |''-@'' |Browse a file's extended attributed, if supported | 23 | 24 | ==== Exit status ==== 25 | 26 | * true if the directory was changed successfully 27 | * false if a change to the home directory was requested, but [[syntax:shellvars#HOME|HOME]] is unset 28 | * false if anything else goes wrong 29 | 30 | ===== Examples ===== 31 | 32 | ==== Change the working directory to the user's home directory ==== 33 | 34 | cd 35 | 36 | ==== Change the working directory to the previous directory ==== 37 | 38 | cd - 39 | 40 | ===== Portability considerations ===== 41 | 42 | ===== See also ===== 43 | * variable [[syntax:shellvars#CDPATH|CDPATH]] 44 | * variable [[syntax:shellvars#HOME|HOME]] 45 | * variable [[syntax:shellvars#OLDPWD|OLDPWD]] 46 | * the ''-P'' option of [[commands:builtin:set|the set builtin command]] 47 | -------------------------------------------------------------------------------- /docs/commands/builtin/cd.md: -------------------------------------------------------------------------------- 1 | # The cd builtin command 2 | 3 | ## Synopsis 4 | 5 | cd [-L|-P] [DIRECTORY] 6 | 7 | cd - 8 | 9 | ## Description 10 | 11 | The `cd` builtin command is used to change the current working directory 12 | 13 | - to the given directory (`cd DIRECTORY`) 14 | - to the previous working directory (`cd -`) as saved in the 15 | [OLDPWD](../../syntax/shellvars.md#OLDPWD) shell variable 16 | - to the user's home directory as specified in the 17 | [HOME](../../syntax/shellvars.md#HOME) environment variable (when used 18 | without a `DIRECTORY` argument) 19 | 20 | The `cd` builtin command searches the directories listed in 21 | [CDPATH](../../syntax/shellvars.md#CDPATH) for a matching directory. 22 | 23 | The default behaviour is to follow symbolic links unless the `-P` option 24 | is given or the shell is configured to do so (see the `-P` option of 25 | [the set builtin command](../../commands/builtin/set.md)). 26 | 27 | ### Options 28 | 29 | |Option|Description| 30 | |------|-----------| 31 | |`-L`|Follow symbolic links (default)| 32 | |`-P`|Do not follow symbolic links| 33 | |`-@`|Browse a file's extended attributed, if supported| 34 | 35 | ### Exit status 36 | 37 | - true if the directory was changed successfully 38 | - false if a change to the home directory was requested, but 39 | [HOME](../../syntax/shellvars.md#HOME) is unset 40 | - false if anything else goes wrong 41 | 42 | ## Examples 43 | 44 | ### Change the working directory to the user's home directory 45 | 46 | cd 47 | 48 | ### Change the working directory to the previous directory 49 | 50 | cd - 51 | 52 | ## Portability considerations 53 | 54 | ## See also 55 | 56 | - variable [CDPATH](../../syntax/shellvars.md#CDPATH) 57 | - variable [HOME](../../syntax/shellvars.md#HOME) 58 | - variable [OLDPWD](../../syntax/shellvars.md#OLDPWD) 59 | - the `-P` option of [the set builtin command](../../commands/builtin/set.md) 60 | -------------------------------------------------------------------------------- /original_source/commands/builtin/shopt.txt: -------------------------------------------------------------------------------- 1 | ====== The shopt builtin command ====== 2 | 3 | The ''shopt'' builtin manages [[internals:shell_options | shell options]], a set of boolean (''on''/''off'') configuration variables that control the behaviour of the shell. 4 | 5 | ===== Synopsis ===== 6 | 7 | 8 | shopt [-pqsu] [-o] 9 | 10 | 11 | ===== Description ===== 12 | 13 | Note: Some of these options and other shell options can also be set with [[commands:builtin:set | the set builtin]]. 14 | 15 | ==== Options ==== 16 | 17 | ^Option^Description^ 18 | |''-o''|Restrict the values of '''' to only those also known by [[commands:builtin:set | the set builtin]]| 19 | |''-p''|Print all shell options and their current value. **Default**.| 20 | |''-q''|Quiet mode. Set exit code if named option is set. For multiple options: ''TRUE'' if all options are set, ''FALSE'' otherwise| 21 | |''-s''|Enable (__s__et) the shell options named by '''' or list all //enabled// options if no names are given| 22 | |''-u''|Disabe (__u__nset) the shell options named by '''' or list all //disabled// options if no names are given| 23 | 24 | As noted above, if only ''-s'' or ''-u'' are given without any option names, only the currently enabled (''-s'') or disabled (''-u'') options are printed. 25 | 26 | ==== Exit code ==== 27 | 28 | When listing options, the exit code is ''TRUE'' (0), if all options are enabled, ''FALSE'' otherwise. 29 | 30 | When setting/unsetting an option, the exit code is ''TRUE'' unless the named option doesn't exitst. 31 | 32 | ===== Examples ====== 33 | 34 | Enable the ''nullglob'' option: 35 | 36 | shopt -s nullglob 37 | 38 | 39 | ===== Portability considerations ====== 40 | 41 | The ''shopt'' command is not portable accross different shells. 42 | 43 | ===== See also ====== 44 | 45 | * Internal: [[commands:builtin:set | The set builtin command]] 46 | * Internal: [[internals:shell_options | List of shell options]] 47 | -------------------------------------------------------------------------------- /docs/syntax/expansion/wordsplit.md: -------------------------------------------------------------------------------- 1 | # Word splitting 2 | 3 | !!! warning "FIXME" 4 | to be continued! 5 | 6 | Word splitting occurs once any of the following expansions are done (and 7 | only then!) 8 | 9 | - [Parameter expansion](../../syntax/pe.md) 10 | - [Command substitution](../../syntax/expansion/cmdsubst.md) 11 | - [Arithmetic expansion](../../syntax/expansion/arith.md) 12 | 13 | Bash will scan the results of these expansions for special `IFS` 14 | characters that mark word boundaries. This is only done on results that 15 | are **not double-quoted**! 16 | 17 | ## Internal Field Separator IFS 18 | 19 | The `IFS` variable holds the characters that Bash sees as word 20 | boundaries in this step. The default contains the characters 21 | 22 | - <space> 23 | - <tab> 24 | - <newline> 25 | 26 | These characters are also assumed when IFS is **unset**. When `IFS` is 27 | **empty** (nullstring), no word splitting is performed at all. 28 | 29 | ## Behaviour 30 | 31 | The results of the expansions mentioned above are scanned for 32 | `IFS`-characters. If **one or more** (in a sequence) of them is found, 33 | the expansion result is split at these positions into multiple words. 34 | 35 | This doesn't happen when the expansion results were **double-quoted**. 36 | 37 | When a null-string (e.g., something that before expanded to 38 | >>nothing<<) is found, it is removed, unless it is quoted (`''` or 39 | `""`). 40 | 41 | **Again note:** Without any expansion beforehand, Bash 42 | won't perform word splitting! In this case, the initial token parsing 43 | is solely responsible. 44 | 45 | ## See also 46 | 47 | - [Introduction to expansion and 48 | substitution](../../syntax/expansion/intro.md) 49 | - [Quoting and escaping](../../syntax/quoting.md) 50 | - [WordSplitting](http://mywiki.wooledge.org/WordSplitting), 51 | [IFS](http://mywiki.wooledge.org/IFS), and 52 | [DontReadLinesWithFor](http://mywiki.wooledge.org/DontReadLinesWithFor) - 53 | Greg's wiki 54 | -------------------------------------------------------------------------------- /original_source/meta/need_love.txt: -------------------------------------------------------------------------------- 1 | ====== Bash Hackers Wiki needs love ====== 2 | 3 | There are things to do. Always. 4 | 5 | ===== Article optics and structure ===== 6 | 7 | Target: A more or less unique structure (done) 8 | 9 | * [[syntax:ccmd:intro]] - bring all mentioned compound command description pages into a format 10 | * SYNOPSIS 11 | * DESCRIPTION 12 | * (with as many sub-topics as needed) 13 | * EXAMPLES 14 | * PORTABILITY CONSIDERATIONS 15 | * SEE ALSO 16 | * do the same with command descriptions (printf, read, ...) 17 | 18 | 19 | ===== Article content and correctness ===== 20 | 21 | In general all pages need review, all the time. If you find anything incorrect, stupid, unclear, just edit the page or write a mail. It's also possible to use the integrated discussion option (below every article). 22 | 23 | Specific needs: 24 | * [[scripting:tutoriallist]] - new tutorials? opinions? etc. 25 | 26 | ===== Article code examples ===== 27 | * [[howto:getopts_tutorial]] - lacks some complex or more sophisticated examples 28 | 29 | ===== Article completeness ===== 30 | * [[scripting:newbie_traps]] - add your personal top newbie traps 31 | * [[internals:shell_options]] - are these all options? 32 | * [[commands:builtin:printf]] - can printf do more? 33 | * [[syntax:shellvars]] - needs complete shell variables 34 | 35 | ===== Greg's BashFAQ mirror ===== 36 | 37 | The code rewrite to mirror Greg's BashFAQ was a bad idea, it doesn't work good. A fix to not lose the links would be to invent some nifty mod_rewrite rules to forward any requests to the namespace to the real BashFAQ wiki. 38 | 39 | **Update:** Just hacked the rewrite rules - the mirror is gone and the mirror URLs redirect to Greg's BashFAQ. 40 | 41 | **Future:** Mirror it as real MoinMoinWiki instance. This won't happen here on the webspace, more on a dedicated server. 42 | 43 | ===== Getopts tutorial ===== 44 | 45 | * more examples 46 | * workaround to use long options: translate long option to short option and replace positional parameters before using getopts -------------------------------------------------------------------------------- /docs/snipplets/largestfile.md: -------------------------------------------------------------------------------- 1 | # Get largest file 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: directory, recursive, 4 | find, crawl LastUpdate_dt: 2013-03-23 Contributors: Dan Douglas type: 5 | snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | One basic pattern for recursive directory traversal with operations on 10 | files at each node. This gets the largest file in each subdirectory. 11 | Toggling some small details will make it return the smallest, or 12 | traverse breadth-first instead of depth-first. 13 | 14 | ``` bash 15 | #!/usr/bin/env bash 16 | # GNU find + bash4 / ksh93v / zsh 17 | # Get the largest file matching pattern in the given directories recursively 18 | ${ZSH_VERSION+false} || emulate ksh 19 | ${BASH_VERSION+shopt -s lastpipe extglob} 20 | 21 | function getLargest { 22 | typeset -A cur top || return 23 | typeset dir x 24 | for dir in "$2"/*/; do 25 | [[ -d $dir ]] || return 0 26 | getLargest "$1" "${dir%/}" || return 27 | top[size]=-1 28 | find "$dir" -maxdepth 1 -type f -name "$1" -printf '%s\0%f\0' | { 29 | while :; do 30 | for x in cur\[{size,name}\]; do 31 | IFS= read -rd '' "$x" || break 2 32 | done 33 | if (( cur[size] > top[size] )); then 34 | top[size]=${cur[size]} top[name]=${cur[name]} 35 | fi 36 | done 37 | printf '%q\n' "${dir}${top[name]}" 38 | } 39 | done 40 | } 41 | 42 | # main pattern dir [ dir ... ] 43 | function main { 44 | if [[ -n $1 ]]; then 45 | typeset dir pattern=$1 46 | shift 47 | for dir; do 48 | [[ -d $dir ]] || return 49 | getLargest "$pattern" "$dir" 50 | done 51 | else 52 | return 1 53 | fi 54 | } 55 | 56 | main "$@" 57 | 58 | # vim: set fenc=utf-8 ff=unix ft=sh : 59 | ``` 60 | 61 | ## More examples 62 | 63 | - 64 | - 65 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/user_select.md: -------------------------------------------------------------------------------- 1 | # User selections 2 | 3 | ## Synopsis 4 | 5 | select ; do 6 | 7 | done 8 | 9 | select in ; do 10 | 11 | done 12 | 13 | # alternative, historical and undocumented syntax 14 | 15 | select 16 | { 17 | 18 | } 19 | 20 | select in 21 | { 22 | 23 | } 24 | 25 | ## Description 26 | 27 | This compound command provides a kind of menu. The user is prompted with 28 | a *numbered list* of the given words, and is asked to input the index 29 | number of the word. If a word was selected, the variable `` is set 30 | to this word, and the [list](../../syntax/basicgrammar.md#lists) `` is 31 | executed. 32 | 33 | If no `in ` is given, then the positional parameters are taken as 34 | words (as if `in "$@"` was written). 35 | 36 | Regardless of the functionality, the *number* the user entered is saved 37 | in the variable `REPLY`. 38 | 39 | Bash knows an alternative syntax for the `select` command, enclosing the 40 | loop body in `{...}` instead of `do ... done`: 41 | 42 | select x in 1 2 3 43 | { 44 | echo $x 45 | } 46 | 47 | This syntax is **not documented** and should not be used. I found the 48 | parser definitions for it in 1.x code, and in modern 4.x code. My guess 49 | is that it's there for compatiblity reasons. This syntax is not 50 | specified by POSIX(R). 51 | 52 | ## Examples 53 | 54 | ``` bash 55 | # select in ; do 56 | # 57 | # done 58 | 59 | 60 | # meaning e.g.: 61 | 62 | clear 63 | echo 64 | echo hit number key 1 2 or 3 then ENTER-key 65 | echo ENTER alone is an empty choice and will loop endlessly until Ctrl-C or Ctrl-D 66 | echo 67 | 68 | select OPTIONX in beer whiskey wine liquor ; do 69 | 70 | echo you ordered a $OPTIONX 71 | break # break avoids endless loop -- second line to be executed always 72 | 73 | done 74 | 75 | # place some if else fi business here 76 | # and explain how it makes sense that $OPTIONX is red but OPTIONX is black 77 | # even though both are variables 78 | ``` 79 | 80 | ## Portability considerations 81 | 82 | ## See also 83 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/grouping_plain.txt: -------------------------------------------------------------------------------- 1 | ====== Grouping commands ====== 2 | 3 | ===== Synopsis ===== 4 | { ; } 5 | 6 | 7 | { 8 | 9 | } 10 | 11 | 12 | ===== Description ===== 13 | 14 | The [[syntax:basicgrammar#lists|list]] '''' is simply executed in the **current** shell environment. The list must be terminated with a **newline** or **semicolon**. For parsing reasons, the curly braces must be separated from '''' by a **semicolon** and **blanks** if they're in the same line! ((Actually any properly terminated compound command will work without extra separator (also in some other shells), **example**: ''{ while sleep 1; do echo ZzZzzZ; done }'' is valid. But this is not documented, infact the documentation explicitly says that a semicolon or a newline must separate the enclosed list. -- thanks ''geirha'' at Freenode))((The main reason is the fact that in shell grammar, the curly braces are not control operators but reserved words -- TheBonsai)) 15 | 16 | This is known as a **group command**. The return status is the [[scripting:basics#exit_codes|exit status (exit code)]] of the list. 17 | 18 | The input and output **filedescriptors** are cumulative: 19 | 20 | { 21 | echo "PASSWD follows" 22 | cat /etc/passwd 23 | echo 24 | echo "GROUPS follows" 25 | cat /etc/group 26 | } >output.txt 27 | 28 | 29 | This compound command also usually is the body of a [[syntax:basicgrammar#shell_function_definitions | function definition]], though not the only compound command that's valid there: 30 | 31 | print_help() { 32 | echo "Options:" 33 | echo "-h This help text" 34 | echo "-f FILE Use config file FILE" 35 | echo "-u USER Run as user USER" 36 | } 37 | 38 | 39 | ===== Examples ===== 40 | ==== A Try-Catch block ==== 41 | 42 | try_catch() { 43 | { # Try-block: 44 | eval "$@" 45 | } || 46 | { # Catch-block: 47 | echo "An error occurred" 48 | return -1 49 | } 50 | } 51 | ===== Portability considerations ===== 52 | 53 | 54 | ===== See also ===== 55 | * [[syntax:ccmd:grouping_subshell | grouping commands in a subshell]] 56 | -------------------------------------------------------------------------------- /original_source/commands/builtin/local.txt: -------------------------------------------------------------------------------- 1 | ====== The local builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | local [option] name[=value] ... 6 | 7 | 8 | ===== Description ===== 9 | 10 | ''local'' is identical to [[commands:builtin:declare|declare]] in every way, and takes all the same options, with 3 exceptions: 11 | * Usage outside of a function is an error. Both ''declare'' and ''local'' within a function have the same effect on variable scope, including the -g option. 12 | * ''local'' with no options prints variable names and values in the same format as ''declare'' with no options, except the variables are filtered to print only locals that were set in the same scope from which ''local'' was called. Variables in parent scopes are not printed. 13 | * If name is ‘-’, the set of shell options is made local to the function in which local is invoked: shell options changed using the set builtin inside the function are restored to their original values when the function returns. The restore is effected as if a series of set commands were executed to restore the values that were in place before the function. 14 | 15 | ===== Portability considerations ===== 16 | 17 | * ''local'' is not specified by POSIX. Most bourne-like shells don't have a builtin called ''local'', but some such as ''dash'' and the busybox shell do. 18 | 19 | * The behavior of function scope is not defined by POSIX, however local variables are implemented widely by bourne-like shells, and behavior differs substantially. Even the''dash'' shell has local variables. 20 | 21 | * In ksh93, using POSIX-style function definitions, ''typeset'' doesn't set ''local'' variables, but rather acts upon variables of the next-outermost scope (e.g. setting attributes). Using ''typeset'' within functions defined using ksh ''function name {'' syntax, variables follow roughly [[http://community.schemewiki.org/?lexical-scope|lexical-scoping]], except that functions themselves don't have scope, just like Bash. This means that even functions defined within a "function's scope" don't have access to non-local variables except through ''namerefs''. 22 | 23 | ===== See also ===== 24 | 25 | * http://wiki.bash-hackers.org/scripting/basics#variable_scope -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bash Hackers Wiki 2 | 3 | The popular [wiki.bash-hackers.org](https://wiki.bash-hackers.org) (original IP address: `83.243.40.67`) site had its DNS expire in April 2023. The owner seems unresponsive, see the [Reddit thread here](https://www.reddit.com/r/bash/comments/12klulf/bashhackersorg_is_now_a_parking_domain/). Fortunately, the web server behind wiki.bash-hackers.org is still running, so I crawled the entire wiki to archive the current versions of all pages. 4 | 5 | This repo tries to preserve and present all this valuable information in a modern way and format, just in case the original wiki won't come back. 6 | 7 | ## Development 8 | 9 | To edit and develop locally install the following packages and run the built in dev webserver: 10 | 11 | ```bash 12 | python3 -m venv env 13 | source env/bin/activate 14 | pip install -r requirements.txt 15 | mkdocs serve 16 | ``` 17 | 18 | ## LICENSE 19 | 20 | As per the original wiki.bash-hackers.org: 21 | 22 | > This wiki and any programs found in this wiki are free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 23 | > 24 | > This wiki and its programs are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 25 | 26 | See [LICENSE](LICENSE) for more details. 27 | 28 | ### Modifications 29 | 30 | The original source files that I scraped from the wiki can be found unmodified in [original_source](original_source/). 31 | 32 | Under [docs](docs/) you will find files that are converted from the original DokuWiki Text to Markdown. Furthermore, I slightly modified the organization of the files to be a better fit for MkDocs Material. 33 | 34 | ## COPYRIGHT 35 | 36 | The original copyright belongs to Jan Schampera (TheBonsai) and subsequent contributors, 2007 - 2023. 37 | 38 | It is important to me that copyright and attribution are given where required. If you're one of the original contributors, and you believe I've violated your copyright in any way, please let me know and write me an email at [mail@flokoe.de](mailto:mail@flokoe.de). 39 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/user_select.txt: -------------------------------------------------------------------------------- 1 | ====== User selections ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | select ; do 6 | 7 | done 8 | 9 | 10 | 11 | select in ; do 12 | 13 | done 14 | 15 | 16 | 17 | # alternative, historical and undocumented syntax 18 | 19 | select 20 | { 21 | 22 | } 23 | 24 | select in 25 | { 26 | 27 | } 28 | 29 | 30 | ===== Description ===== 31 | This compound command provides a kind of menu. The user is prompted with a //numbered list// of the given words, and is asked to input the index number of the word. If a word was selected, the variable '''' is set to this word, and the [[syntax:basicgrammar#lists | list]] '''' is executed. 32 | 33 | If no ''in '' is given, then the positional parameters are taken as words (as if ''in "$@"'' was written). 34 | 35 | Regardless of the functionality, the //number// the user entered is saved in the variable ''REPLY''. 36 | 37 | Bash knows an alternative syntax for the ''select'' command, enclosing the loop body in ''{...}'' instead of ''do ... done'': 38 | 39 | select x in 1 2 3 40 | { 41 | echo $x 42 | } 43 | 44 | This syntax is **not documented** and should not be used. I found the parser definitions for it in 1.x code, and in modern 4.x code. My guess is that it's there for compatiblity reasons. This syntax is not specified by POSIX(R). 45 | 46 | ===== Examples ===== 47 | 48 | # select in ; do 49 | # 50 | # done 51 | 52 | 53 | # meaning e.g.: 54 | 55 | clear 56 | echo 57 | echo hit number key 1 2 or 3 then ENTER-key 58 | echo ENTER alone is an empty choice and will loop endlessly until Ctrl-C or Ctrl-D 59 | echo 60 | 61 | select OPTIONX in beer whiskey wine liquor ; do 62 | 63 | echo you ordered a $OPTIONX 64 | break # break avoids endless loop -- second line to be executed always 65 | 66 | done 67 | 68 | # place some if else fi business here 69 | # and explain how it makes sense that $OPTIONX is red but OPTIONX is black 70 | # even though both are variables 71 | 72 | ===== Portability considerations ===== 73 | 74 | ===== See also ===== 75 | 76 | -------------------------------------------------------------------------------- /original_source/snipplets/kill_bg_job_without_message.txt: -------------------------------------------------------------------------------- 1 | ====== Kill a background job without a message ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: kill, process management, jobs 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Jan Schampera 7 | type: snipplet 8 | ---- 9 | 10 | When you start background jobs from within a script (non-interactive shell) and kill it afterwards, you will get a message from the shell that the process was terminated. 11 | 12 | Example: 13 | 14 | #!/bin/bash 15 | 16 | # example background process 17 | sleep 300 & 18 | 19 | # get the PID 20 | BG_PID=$! 21 | 22 | # kill it, hard and mercyless 23 | kill -9 $BG_PID 24 | 25 | echo "Yes, we killed it" 26 | 27 | 28 | You will get something like this: 29 | 30 | $ ./bg_kill1.sh 31 | ./bg_kill1.sh: line 11: 3413 Killed sleep 300 32 | Yes, we killed it 33 | 34 | 35 | This is more or less a normal message. And it can't be easily redirected since it's the shell itself that yells this message, not the command ''kill'' or something else. You would have to redirect the whole script's output. 36 | 37 | It's also useless to temporarily redirect ''stderr'' when you call the ''kill'' command, since the successful termination of the job, the termination of the ''kill'' command and the message from the shell may not happen at the same time. And a blind ''sleep'' after the ''kill'' would be just a workaround. 38 | 39 | The solution is relatively easy: The shell spits that message because it controls the background job, and when it terminates, the shell will tell you whenever possible. Now you just need to tell your shell that it is no longer responsible for that background process. This is done by the ''disown'' command, which can take an internal shell job number (like ''%1'') or a process ID as argument. 40 | 41 | 42 | #!/bin/bash 43 | 44 | # example background process 45 | sleep 300 & 46 | 47 | # get the PID 48 | BG_PID=$! 49 | 50 | ### HERE, YOU TELL THE SHELL TO NOT CARE ANY MORE ### 51 | disown $BG_PID 52 | ### 53 | 54 | 55 | # kill it, hard and mercyless, now without a trace 56 | kill -9 $BG_PID 57 | 58 | echo "Yes, we killed it" 59 | 60 | 61 | That way, you can run and kill background processes without disturbing messages. 62 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/grouping_plain.md: -------------------------------------------------------------------------------- 1 | # Grouping commands 2 | 3 | ## Synopsis 4 | 5 | { ; } 6 | 7 | { 8 | 9 | } 10 | 11 | ## Description 12 | 13 | The [list](../../syntax/basicgrammar.md#lists) `` is simply executed in 14 | the **current** shell environment. The list must be terminated with a 15 | **newline** or **semicolon**. For parsing reasons, the curly braces must 16 | be separated from `` by a **semicolon** and **blanks** if they're 17 | in the same line! [^1][^2] 18 | 19 | This is known as a **group command**. The return status is the [exit 20 | status (exit code)](../../scripting/basics.md#exit_codes) of the list. 21 | 22 | The input and output **filedescriptors** are cumulative: 23 | 24 | { 25 | echo "PASSWD follows" 26 | cat /etc/passwd 27 | echo 28 | echo "GROUPS follows" 29 | cat /etc/group 30 | } >output.txt 31 | 32 | This compound command also usually is the body of a [function 33 | definition](../../syntax/basicgrammar.md#shell_function_definitions), though not 34 | the only compound command that's valid there: 35 | 36 | print_help() { 37 | echo "Options:" 38 | echo "-h This help text" 39 | echo "-f FILE Use config file FILE" 40 | echo "-u USER Run as user USER" 41 | } 42 | 43 | ## Examples 44 | 45 | ### A Try-Catch block 46 | 47 | try_catch() { 48 | { # Try-block: 49 | eval "$@" 50 | } || 51 | { # Catch-block: 52 | echo "An error occurred" 53 | return -1 54 | } 55 | } 56 | 57 | ## Portability considerations 58 | 59 | ## See also 60 | 61 | * [[syntax:ccmd:grouping_subshell | grouping commands in a subshell]] 62 | 63 | [^1]: Actually any properly terminated compound command will work 64 | without extra separator (also in some other shells), **example**: 65 | `{ while sleep 1; do echo ZzZzzZ; done }` is valid. But this is not 66 | documented, infact the documentation explicitly says that a 67 | semicolon or a newline must separate the enclosed list. -- thanks 68 | `geirha` at Freenode 69 | 70 | [^2]: The main reason is the fact that in shell grammar, the curly 71 | braces are not control operators but reserved words -- TheBonsai 72 | -------------------------------------------------------------------------------- /original_source/dict/terms/parameter.txt: -------------------------------------------------------------------------------- 1 | ====== Parameter ====== 2 | 3 | Also the article for: __variable__, __positional parameter__, __special parameter__ 4 | 5 | In Bash, a parameter is simply an entity that stores values and can be referenced. Depending on the type, the parameters can be set directly, only indirectly, or only automatically by the shell. 6 | 7 | Bash knows 3 types of parameters: 8 | * variables 9 | * positional parameters 10 | * special parameters 11 | 12 | ===== variables ===== 13 | 14 | A shell variable is a parameter denoted by a //variable name//: 15 | * containing only alphanumeric characters and underscores 16 | * beginning with an alphabetic character or an underscore 17 | 18 | A value can be assigned to a variable, using the variable's name and an equal-sign: 19 | NAME=VALUE 20 | 21 | Once a variable is set, it exists and can only be unset by the ''unset'' builtin command. 22 | 23 | The nullstring is a valid value: 24 | 25 | NAME= 26 | NAME="" 27 | 28 | 29 | 30 | ===== positional parameters ===== 31 | 32 | A positional parameter is denoted by a number other than ''0'' (zero). 33 | 34 | Positional parameters reflect the shell's arguments that are not given to the shell itself (in practise, the script arguments, also the function arguments). You can't directly assign to the positional parameters, however, [[commands:builtin:set | the set builtin command]] can be used to indirectly set them. 35 | 36 | The first to ninth positional parameter is referenced by ''$1'' to ''$9''. All following positional parameters (tenth and above) must be referenced by the number given in curly braces, i.e., ''${10}'' or ''${432}''. 37 | 38 | Unlike popular belief, ''$0'' is //not a positional parameter//. 39 | 40 | See also the [[scripting:posparams | scripting article about handling positional parameters]]. 41 | 42 | ===== special parameters ===== 43 | 44 | There are a bunch of special parameters, which are set by the shell. Direct assignment to them is not possible. These parameter names are formed of one character. 45 | 46 | Please see [[syntax:shellvars]]. 47 | 48 | 49 | 50 | ===== See also ===== 51 | * Syntax article, internal: [[syntax:pe]] 52 | * Syntax article, internal: [[syntax:shellvars]] 53 | * Scripting article, internal: [[scripting:posparams]] 54 | 55 | -------------------------------------------------------------------------------- /docs/dict/parameter.md: -------------------------------------------------------------------------------- 1 | # Parameter 2 | 3 | Also the article for: variable, positional 4 | parameter, special parameter 5 | 6 | In Bash, a parameter is simply an entity that stores values and can be 7 | referenced. Depending on the type, the parameters can be set directly, 8 | only indirectly, or only automatically by the shell. 9 | 10 | Bash knows 3 types of parameters: 11 | 12 | - variables 13 | - positional parameters 14 | - special parameters 15 | 16 | ## variables 17 | 18 | A shell variable is a parameter denoted by a *variable name*: 19 | 20 | - containing only alphanumeric characters and underscores 21 | - beginning with an alphabetic character or an underscore 22 | 23 | A value can be assigned to a variable, using the variable's name and an 24 | equal-sign: 25 | 26 | NAME=VALUE 27 | 28 | Once a variable is set, it exists and can only be unset by the `unset` 29 | builtin command. 30 | 31 | The nullstring is a valid value: 32 | 33 | NAME= 34 | NAME="" 35 | 36 | ## positional parameters 37 | 38 | A positional parameter is denoted by a number other than `0` (zero). 39 | 40 | Positional parameters reflect the shell's arguments that are not given 41 | to the shell itself (in practise, the script arguments, also the 42 | function arguments). You can't directly assign to the positional 43 | parameters, however, [the set builtin command](../commands/builtin/set.md) 44 | can be used to indirectly set them. 45 | 46 | The first to ninth positional parameter is referenced by `$1` to `$9`. 47 | All following positional parameters (tenth and above) must be referenced 48 | by the number given in curly braces, i.e., `${10}` or `${432}`. 49 | 50 | Unlike popular belief, `$0` is *not a positional parameter*. 51 | 52 | See also the [scripting article about handling positional 53 | parameters](../scripting/posparams.md). 54 | 55 | ## special parameters 56 | 57 | There are a bunch of special parameters, which are set by the shell. 58 | Direct assignment to them is not possible. These parameter names are 59 | formed of one character. 60 | 61 | Please see [shellvars](../syntax/shellvars.md). 62 | 63 | ## See also 64 | 65 | - Syntax article, internal: [pe](../syntax/pe.md) 66 | - Syntax article, internal: [shellvars](../syntax/shellvars.md) 67 | - Scripting article, internal: [posparams](../scripting/posparams.md) 68 | -------------------------------------------------------------------------------- /original_source/wishes.txt: -------------------------------------------------------------------------------- 1 | ====== Wishlist ====== 2 | 3 | **NOTE:** Due to neverending SPAM from various IPs (the usual pharmacy-links and whatnot nonsens) this page was made readonly. 4 | 5 | Another way of submitting wishes is the following form: 6 | {{contact>subj=Wiki: wishlist}} 7 | 8 | 9 | ===== Token Recognition and Shell Grammar ===== 10 | 11 | a more human-readable version of the following topics: 12 | 13 | * [[http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_03]] 14 | * [[http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_10]] 15 | 16 | ===== General ===== 17 | A simplified version of `man bash' and interesting bash tricks.:-) 18 | > The whole site is meant to be like that: a simplified or better human-readable collection of manpage snipplets. Maybe a page with the main topics of bash manpage that link to the proper articles would be good (I just don't have enough articles heh) - a kind of summary page --- Jan 19 | 20 | 21 | ===== Some ideas ===== 22 | 23 | **hmm maybe some of this stuff could make it somewhere to the wiki...:)** 24 | 25 | * an article about how to do ksh coprocess in bash (:V4: may be obsolete regarding [[bash4 | Bash 4 features]]) 26 | - single way -> process substitution 27 | - 2 way name pipes 28 | * let's write a interactive tutorial script that teaches readline/bash (like C-h t in emacs, or vimtutor or vilearn) 29 | * programmable history: http://pastebin.bash-hackers.org/index.php?show=22 30 | 31 | ===== Implemented ===== 32 | 33 | ==== Bash For Loop Multi-word lines ==== 34 | 35 | From this solution on modifying the internal Field Separator (IFS) in bash I found here: 36 | * http://linux.derkeiler.com/Mailing-Lists/Debian/2006-08/msg00462.html 37 | 38 | > added to [[syntax:ccmd:classic_for|the for-loop-article]] as example, but also made some critical comments; thanks --- Jan 39 | 40 | ==== Getopts tutorial ==== 41 | * My school offers a UNIX programming course (C, shell, etc.). I use this site extensively to help my friends taking this course learn concepts such as I/O redirection etc. As it gets more advanced they need to do option parsing. Therefore I would like to see a "getopts illustrated" article or some such, showing the breakdown of how it parses parameters. 42 | * "[[howto:getopts_tutorial]]" is a first step for the getopts stuff - provide ideas -------------------------------------------------------------------------------- /docs/commands/builtin/kill.md: -------------------------------------------------------------------------------- 1 | # The kill builtin command 2 | 3 | ## Synopsis 4 | 5 | kill [-s SIGNAL | -n SIGNALNUMBER | -SIGNAL] PID|JOB 6 | 7 | kill -l|-L [SIGNAL...] 8 | 9 | ## Description 10 | 11 | The `kill` command is used to send signals to processes specified by 12 | their `PID` or their `JOB`-specification. 13 | 14 | The signal(s) to be specified can have the following formats: 15 | 16 | - Numerical: The signal is specified using its constant numeric value. 17 | Be aware that not all systems have identical numbers for the 18 | signals. 19 | - Symbolic (long): The signal is specified using the same name that is 20 | used for the constant/macro in the C API (`SIG`) 21 | - Symbolic (short): The signal is specified using the name from the C 22 | API without the `SIG`-prefix (``) 23 | 24 | Without any specified signal, the command sends the `SIGTERM`-signal. 25 | 26 | The `kill` command is a Bash builtin command instead of relying on the 27 | external `kill` command of the operating system to 28 | 29 | - be able to use shell job specifications instead of Unix process IDs 30 | - be able to send signals ("kill something") also, when your process 31 | limit is reached 32 | 33 | ### Options 34 | 35 | |Option|Description| 36 | |------|-----------| 37 | |`-s SIGNAL`|specifies the signal to send| 38 | |`-n SIGNALNUMBER`|specifies the signal to send| 39 | |`-SIGNAL`|specifies the signal to send| 40 | |`-l [SIGNAL...]`|Lists supported/known signal numbers and their symbolic name. If `SIGNAL` is given, only list this signal, translated (if a number is given the symbolic name is printed, and vice versa)| 41 | |`-L [SIGNAL...]`|Same as `-l [SIGNAL]` (compatiblity option)| 42 | 43 | ### Return status 44 | 45 | |Status|Reason| 46 | |------|------| 47 | |0|no error/success| 48 | |!=0|invalid option| 49 | |!=0|invalid signal specification| 50 | |!=0|error returned by the system function (e.g. insufficient permissions to send to a specific process)| 51 | 52 | ## Examples 53 | 54 | ### List supported signals 55 | 56 | kill -l 57 | 58 | ### Send KILL to a process ID 59 | 60 | kill -9 12345 61 | 62 | kill -KILL 12345 63 | 64 | kill -SIGKILL 12345 65 | 66 | ## Portability considerations 67 | 68 | - POSIX(R) and ISO C only standardize symbolic signal names (no 69 | numbers) and a default action 70 | 71 | ## See also 72 | -------------------------------------------------------------------------------- /docs/commands/builtin/trap.md: -------------------------------------------------------------------------------- 1 | # The trap builtin command 2 | 3 | ## Synopsis 4 | 5 | trap [-lp] [[ARGUMENT] SIGNAL] 6 | 7 | ## Description 8 | 9 | The `trap` command is used to "trap" signals and other events. In this 10 | context, "trapping" means to install handler code. 11 | 12 | The shell code `ARGUMENT` is to be read and executed whenever the shell 13 | receives a signal or another event `SIGNAL`. The given `SIGNAL` 14 | specification can be 15 | 16 | - the name of a signal with the SIG prefix, e.g. `SIGTERM` 17 | - the name of a signal without the SIG prefix, e.g. `TERM` 18 | - the number of a signal (see `trap -l`), e.g. `15` 19 | - the name or number of a special event (see table below), e.g. `EXIT` 20 | 21 | Without any options or operands, `trap` prints a list of installed traps 22 | in a reusable format (equivalent to the `-p` option). 23 | 24 | Special `ARGUMENT`s 25 | 26 | - if `ARGUMENT` is absent or `-` (dash), the signal/event handler is 27 | reset to its original value 28 | - if `ARGUMENT` is the null string, the signal/event is ignored 29 | 30 | Special events 31 | 32 | |Name|Code|Description| 33 | |----|----|-----------| 34 | |`EXIT`|0|executed on shell exit| 35 | |`DEBUG`||executed before every simple command| 36 | |`RETURN`||executed when a shell function or a sourced code finishes executing| 37 | |`ERR`||executed each time a command's failure would cause the shell to exit when the [`-e` option (`errexit`)](../../commands/builtin/set.md) is enabled| 38 | 39 | ### Options 40 | 41 | |Option|Description| 42 | |------|-----------| 43 | |`-l`|print a list of signal names and their corresponding numbers| 44 | |`-p`|display the trap commands associated with each signal specification in a reusable format| 45 | 46 | ### Return status 47 | 48 | |Status|Reason| 49 | |------|------| 50 | |0|no error/success| 51 | |!=0|invalid option| 52 | |!=0|invalid signal specification| 53 | 54 | ## Examples 55 | 56 | ### List installed traps 57 | 58 | trap 59 | 60 | ### Ignore terminal interrupt (Ctrl-C, SIGINT) 61 | 62 | trap '' INT 63 | 64 | ## Portability considerations 65 | 66 | - `trap` is specified by POSIX(R) without the `-l` and `-p` options 67 | - in POSIX(R), beside signals, only `EXIT` (0) is valid as an event 68 | 69 | ## See also 70 | 71 | - [the set command](../../commands/builtin/set.md) for the `-e` (`errexit`) 72 | option 73 | -------------------------------------------------------------------------------- /docs/commands/builtin/local.md: -------------------------------------------------------------------------------- 1 | # The local builtin command 2 | 3 | ## Synopsis 4 | 5 | local [option] name[=value] ... 6 | 7 | ## Description 8 | 9 | `local` is identical to [declare](../../commands/builtin/declare.md) in every 10 | way, and takes all the same options, with 3 exceptions: 11 | 12 | - Usage outside of a function is an error. Both `declare` and `local` 13 | within a function have the same effect on variable scope, including 14 | the -g option. 15 | - `local` with no options prints variable names and values in the same 16 | format as `declare` with no options, except the variables are 17 | filtered to print only locals that were set in the same scope from 18 | which `local` was called. Variables in parent scopes are not 19 | printed. 20 | - If name is '-', the set of shell options is made local to the 21 | function in which local is invoked: shell options changed using the 22 | set builtin inside the function are restored to their original 23 | values when the function returns. The restore is effected as if a 24 | series of set commands were executed to restore the values that were 25 | in place before the function. 26 | 27 | ## Portability considerations 28 | 29 | - `local` is not specified by POSIX. Most bourne-like shells don't 30 | have a builtin called `local`, but some such as `dash` and the 31 | busybox shell do. 32 | 33 | - The behavior of function scope is not defined by POSIX, however 34 | local variables are implemented widely by bourne-like shells, and 35 | behavior differs substantially. Even the`dash` shell has local 36 | variables. 37 | 38 | - In ksh93, using POSIX-style function definitions, `typeset` doesn't 39 | set `local` variables, but rather acts upon variables of the 40 | next-outermost scope (e.g. setting attributes). Using `typeset` 41 | within functions defined using ksh `function name {` syntax, 42 | variables follow roughly 43 | [lexical-scoping](http://community.schemewiki.org/?lexical-scope), 44 | except that functions themselves don't have scope, just like Bash. 45 | This means that even functions defined within a "function's 46 | scope" don't have access to non-local variables except through 47 | `namerefs`. 48 | 49 | ## See also 50 | 51 | - [The basics of shell scripting: Variable scope](../../scripting/basics.md#variable-scope) 52 | -------------------------------------------------------------------------------- /docs/snipplets/kill_bg_job_without_message.md: -------------------------------------------------------------------------------- 1 | # Kill a background job without a message 2 | 3 | ---- dataentry snipplet ---- snipplet_tags: kill, process 4 | management, jobs LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera 5 | type: snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | When you start background jobs from within a script (non-interactive 10 | shell) and kill it afterwards, you will get a message from the shell 11 | that the process was terminated. 12 | 13 | Example: 14 | 15 | #!/bin/bash 16 | 17 | # example background process 18 | sleep 300 & 19 | 20 | # get the PID 21 | BG_PID=$! 22 | 23 | # kill it, hard and mercyless 24 | kill -9 $BG_PID 25 | 26 | echo "Yes, we killed it" 27 | 28 | You will get something like this: 29 | 30 | $ ./bg_kill1.sh 31 | ./bg_kill1.sh: line 11: 3413 Killed sleep 300 32 | Yes, we killed it 33 | 34 | This is more or less a normal message. And it can't be easily 35 | redirected since it's the shell itself that yells this message, not the 36 | command `kill` or something else. You would have to redirect the whole 37 | script's output. 38 | 39 | It's also useless to temporarily redirect `stderr` when you call the 40 | `kill` command, since the successful termination of the job, the 41 | termination of the `kill` command and the message from the shell may not 42 | happen at the same time. And a blind `sleep` after the `kill` would be 43 | just a workaround. 44 | 45 | The solution is relatively easy: The shell spits that message because it 46 | controls the background job, and when it terminates, the shell will tell 47 | you whenever possible. Now you just need to tell your shell that it is 48 | no longer responsible for that background process. This is done by the 49 | `disown` command, which can take an internal shell job number (like 50 | `%1`) or a process ID as argument. 51 | 52 | #!/bin/bash 53 | 54 | # example background process 55 | sleep 300 & 56 | 57 | # get the PID 58 | BG_PID=$! 59 | 60 | ### HERE, YOU TELL THE SHELL TO NOT CARE ANY MORE ### 61 | disown $BG_PID 62 | ### 63 | 64 | 65 | # kill it, hard and mercyless, now without a trace 66 | kill -9 $BG_PID 67 | 68 | echo "Yes, we killed it" 69 | 70 | That way, you can run and kill background processes without disturbing 71 | messages. 72 | -------------------------------------------------------------------------------- /docs/snipplets/wrapperargs.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - arguments 4 | - quoting 5 | - escape 6 | - quote 7 | - wrapper 8 | - generate 9 | --- 10 | 11 | # Generate code with own arguments properly quoted 12 | 13 | There are situations where Bash code needs to generate Bash code. A 14 | script that writes out another script the user or cron may start, for 15 | example. 16 | 17 | The general issue is easy, just write out text to the file. 18 | 19 | A specific detail of it is tricky: If the generated script needs to call 20 | a command using the arguments the first original script got, you have 21 | problem in writing out the correct code. 22 | 23 | I.e. if you run your generator script like 24 | 25 | ./myscript "give me 'some' water" 26 | 27 | then this script should generate code that looks like 28 | 29 | echo give me 'some' water" 30 | 31 | you need correct escapes or quotes to not generate shell special 32 | characters out of normal text (like embedded dollar signs `$`). 33 | 34 | **Solution:** 35 | 36 | A loop over the own arguments that writes out properly quoted/escaped 37 | code to the generated script file 38 | 39 | There are two (maybe more) easy options: 40 | 41 | - writing out singlequoted strings and handle the embedded 42 | singlequotes 43 | - the [printf command](../commands/builtin/printf.md) knows the `%q` format 44 | specification, which will print a string (like `%s` does), but with 45 | all shell special characters escaped 46 | 47 | ## Using singlequoted string 48 | 49 | #!/bin/bash 50 | 51 | # first option: 52 | # generate singlequoted strings out of your own arguments and handle embedded singlequotes 53 | # here to call 'echo' in the generated script 54 | 55 | { 56 | printf "#!/bin/bash\n\n" 57 | printf "echo " 58 | for arg; do 59 | arg=${arg/\'/\'\\\'\'} 60 | printf "'%s' " "${arg}" 61 | done 62 | 63 | printf "\n" 64 | } >s2 65 | 66 | The generated script will look like: 67 | 68 | #!/bin/bash 69 | 70 | echo 'fir$t' 'seco "ond"' 'thir'\''d' 71 | 72 | ## Using printf 73 | 74 | The second method is easier, though more or less Bash-only (due to the 75 | `%q` in printf): 76 | 77 | #!/bin/bash 78 | 79 | { 80 | printf "#!/bin/bash\n\n" 81 | printf "echo " 82 | for arg; do 83 | printf '%q ' "$arg" 84 | done 85 | 86 | printf "\n" 87 | } >s2 88 | 89 | The generated script will look like: 90 | 91 | #!/bin/bash 92 | 93 | echo fir\$t seco\ \"ond\" thir\'d 94 | -------------------------------------------------------------------------------- /original_source/commands/builtin/trap.txt: -------------------------------------------------------------------------------- 1 | ====== The trap builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | trap [-lp] [[ARGUMENT] SIGNAL] 5 | 6 | ===== Description ===== 7 | The ''trap'' command is used to "trap" signals and other events. In this context, "trapping" means to install handler code. 8 | 9 | The shell code ''ARGUMENT'' is to be read and executed whenever the shell receives a signal or another event ''SIGNAL''. The given ''SIGNAL'' specification can be 10 | * the name of a signal with the SIG prefix, e.g. ''SIGTERM'' 11 | * the name of a signal without the SIG prefix, e.g. ''TERM'' 12 | * the number of a signal (see ''trap -l''), e.g. ''15'' 13 | * the name or number of a special event (see table below), e.g. ''EXIT'' 14 | 15 | Without any options or operands, ''trap'' prints a list of installed traps in a reusable format (equivalent to the ''-p'' option). 16 | 17 | Special ''ARGUMENT''s 18 | * if ''ARGUMENT'' is absent or ''-'' (dash), the signal/event handler is reset to its original value 19 | * if ''ARGUMENT'' is the null string, the signal/event is ignored 20 | 21 | Special events 22 | ^Name ^Code ^Description ^ 23 | |''EXIT'' |0 |executed on shell exit | 24 | |''DEBUG'' | |executed before every simple command | 25 | |''RETURN'' | |executed when a shell function or a sourced code finishes executing | 26 | |''ERR'' | |executed each time a command's failure would cause the shell to exit when the [[commands:builtin:set|''-e'' option (''errexit'')]] is enabled | 27 | 28 | ==== Options ==== 29 | 30 | ^Option ^Description ^ 31 | |''-l'' |print a list of signal names and their corresponding numbers | 32 | |''-p'' |display the trap commands associated with each signal specification in a reusable format | 33 | 34 | ==== Return status ==== 35 | 36 | ^Status ^Reason ^ 37 | |0 |no error/success | 38 | |!=0 |invalid option | 39 | |!=0 |invalid signal specification | 40 | 41 | ===== Examples ===== 42 | 43 | ==== List installed traps ==== 44 | 45 | 46 | trap 47 | 48 | 49 | ==== Ignore terminal interrupt (Ctrl-C, SIGINT) ==== 50 | 51 | 52 | trap '' INT 53 | 54 | 55 | ===== Portability considerations ===== 56 | 57 | * ''trap'' is specified by POSIX(R) without the ''-l'' and ''-p'' options 58 | * in POSIX(R), beside signals, only ''EXIT'' (0) is valid as an event 59 | 60 | ===== See also ===== 61 | 62 | * [[commands:builtin:set|the set command]] for the ''-e'' (''errexit'') option 63 | -------------------------------------------------------------------------------- /original_source/commands/builtin/kill.txt: -------------------------------------------------------------------------------- 1 | ====== The kill builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | kill [-s SIGNAL | -n SIGNALNUMBER | -SIGNAL] PID|JOB 5 | kill -l|-L [SIGNAL...] 6 | 7 | ===== Description ===== 8 | The ''kill'' command is used to send signals to processes specified by their ''PID'' or their ''JOB''-specification. 9 | 10 | The signal(s) to be specified can have the following formats: 11 | * Numerical: The signal is specified using its constant numeric value. Be aware that not all systems have identical numbers for the signals. 12 | * Symbolic (long): The signal is specified using the same name that is used for the constant/macro in the C API (''SIG'') 13 | * Symbolic (short): The signal is specified using the name from the C API without the ''SIG''-prefix ('''') 14 | 15 | Without any specified signal, the command sends the ''SIGTERM''-signal. 16 | 17 | The ''kill'' command is a Bash builtin command instead of relying on the external ''kill'' command of the operating system to 18 | * be able to use shell job specifications instead of Unix process IDs 19 | * be able to send signals ("kill something") also, when your process limit is reached 20 | 21 | ==== Options ==== 22 | 23 | ^Option ^Description ^ 24 | |''-s SIGNAL'' |specifies the signal to send | 25 | |''-n SIGNALNUMBER'' |specifies the signal to send | 26 | |''-SIGNAL'' |specifies the signal to send | 27 | |''-l [SIGNAL...]'' |Lists supported/known signal numbers and their symbolic name. If ''SIGNAL'' is given, only list this signal, translated (if a number is given the symbolic name is printed, and vice versa) | 28 | |''-L [SIGNAL...]'' |Same as ''-l [SIGNAL]'' (compatiblity option) | 29 | 30 | ==== Return status ==== 31 | 32 | ^Status ^Reason ^ 33 | |0 |no error/success | 34 | |!=0 |invalid option | 35 | |!=0 |invalid signal specification | 36 | |!=0 |error returned by the system function (e.g. insufficient permissions to send to a specific process) | 37 | 38 | ===== Examples ===== 39 | 40 | ==== List supported signals ==== 41 | 42 | 43 | kill -l 44 | 45 | 46 | ==== Send KILL to a process ID ==== 47 | 48 | 49 | kill -9 12345 50 | 51 | 52 | 53 | kill -KILL 12345 54 | 55 | 56 | 57 | kill -SIGKILL 12345 58 | 59 | 60 | ===== Portability considerations ===== 61 | 62 | * POSIX(R) and ISO C only standardize symbolic signal names (no numbers) and a default action 63 | 64 | ===== See also ===== 65 | 66 | -------------------------------------------------------------------------------- /docs/commands/builtin/exec.md: -------------------------------------------------------------------------------- 1 | # The exec builtin command 2 | 3 | ## Synopsis 4 | 5 | exec [-a NAME] [-cl] [COMMAND] [ARG...] [REDIRECTION...] 6 | 7 | ## Description 8 | 9 | The `exec` builtin command is used to 10 | 11 | - **replace** the shell with a given program (executing it, **not as 12 | new process**) 13 | - set redirections for the program to execute or for the current shell 14 | 15 | If only redirections are given, the redirections affect the current 16 | shell without executing any program. 17 | 18 | ### Options 19 | 20 | |Option|Description| 21 | |------|-----------| 22 | |`-a NAME`|Passes `NAME` as zeroth argument for the program to be executed| 23 | |`-c`|Execute the program with an empty (cleared) environment| 24 | |`-l`|Prepends a dash (`-`) to the zeroth argument of the program to be executed, similar to what the `login` program does| 25 | 26 | ### Exit status 27 | 28 | - on redirection errors it returns 1, otherwise 0 29 | - on exec failures: 30 | - a non-interactive shell terminates; if the [shell option 31 | execfail](../../internals/shell_options.md#execfail) is set `exec` 32 | returns failure 33 | - in an interactive shell, `exec` returns failure 34 | 35 | ## Examples 36 | 37 | ### Wrapper around a program 38 | 39 | ``` bash 40 | myprog=/bin/ls 41 | echo "This is the wrapper script, it will exec $myprog" 42 | 43 | # do some vodoo here, probably change the arguments etc. 44 | # well, stuff a wrapper is there for 45 | 46 | exec "$myprog" "$@" 47 | ``` 48 | 49 | ### Open a file as input for the script 50 | 51 | ``` bash 52 | # open it 53 | exec 3< input.txt 54 | 55 | # for example: read one line from the file(-descriptor) 56 | read -u 3 LINE 57 | # or 58 | read LINE <&3 59 | 60 | # finally, close it 61 | exec 3<&- 62 | ``` 63 | 64 | ### Overall script logfile 65 | 66 | To redirect the whole `stdout` and `stderr` of the shell or shellscript 67 | to a file, you can use the `exec` builtin command: 68 | 69 | ``` bash 70 | exec >/var/adm/my.log 2>&1 71 | 72 | # script continues here... 73 | ``` 74 | 75 | ## Portability considerations 76 | 77 | *POSIX(r) specifies error code ranges: 78 | * if ''exec'' can't find the program to execute, the error code shall be 126 79 | * on a redirection error, the error code shall be between 1 and 125 80 | * the ''-a NAME'' option appeared in Bash 4.2-alpha 81 | * POSIX(r) does **not** specify any options for ''exec'' (like ''-c'', ''-l'', ''-a NAME''). 82 | 83 | ## See also 84 | 85 | - [redirection](../../syntax/redirection.md) 86 | -------------------------------------------------------------------------------- /original_source/commands/builtin/exec.txt: -------------------------------------------------------------------------------- 1 | ====== The exec builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | exec [-a NAME] [-cl] [COMMAND] [ARG...] [REDIRECTION...] 5 | 6 | ===== Description ===== 7 | The ''exec'' builtin command is used to 8 | * **replace** the shell with a given program (executing it, **not as new process**) 9 | * set redirections for the program to execute or for the current shell 10 | 11 | If only redirections are given, the redirections affect the current shell without executing any program. 12 | 13 | ==== Options ==== 14 | 15 | ^Option^Description^ 16 | |''-a NAME'' |Passes ''NAME'' as zeroth argument for the program to be executed | 17 | |''-c'' |Execute the program with an empty (cleared) environment | 18 | |''-l'' |Prepends a dash (''-'') to the zeroth argument of the program to be executed, similar to what the ''login'' program does | 19 | 20 | ==== Exit status ==== 21 | 22 | * on redirection errors it returns 1, otherwise 0 23 | * on exec failures: 24 | * a non-interactive shell terminates; if the [[internals:shell_options#execfail | shell option execfail]] is set ''exec'' returns failure 25 | * in an interactive shell, ''exec'' returns failure 26 | 27 | ===== Examples ===== 28 | 29 | ==== Wrapper around a program ==== 30 | 31 | myprog=/bin/ls 32 | echo "This is the wrapper script, it will exec $myprog" 33 | 34 | # do some vodoo here, probably change the arguments etc. 35 | # well, stuff a wrapper is there for 36 | 37 | exec "$myprog" "$@" 38 | 39 | 40 | ==== Open a file as input for the script ==== 41 | 42 | # open it 43 | exec 3< input.txt 44 | 45 | # for example: read one line from the file(-descriptor) 46 | read -u 3 LINE 47 | # or 48 | read LINE <&3 49 | 50 | # finally, close it 51 | exec 3<&- 52 | 53 | 54 | ==== Overall script logfile ==== 55 | 56 | To redirect the whole ''stdout'' and ''stderr'' of the shell or shellscript to a file, you can use the ''exec'' builtin command: 57 | 58 | exec >/var/adm/my.log 2>&1 59 | 60 | # script continues here... 61 | 62 | 63 | ===== Portability considerations ===== 64 | 65 | *POSIX(r) specifies error code ranges: 66 | * if ''exec'' can't find the program to execute, the error code shall be 126 67 | * on a redirection error, the error code shall be between 1 and 125 68 | * the ''-a NAME'' option appeared in Bash 4.2-alpha 69 | * POSIX(r) does **not** specify any options for ''exec'' (like ''-c'', ''-l'', ''-a NAME''). 70 | 71 | ===== See also ===== 72 | * [[syntax:redirection]] 73 | -------------------------------------------------------------------------------- /docs/howto/testing-your-scripts.md: -------------------------------------------------------------------------------- 1 | The one of the simplest way to check your bash/sh scripts is run it and 2 | check it output or run it and check the result. This tutorial shows 3 | how-to use [bashtest](https://github.com/pahaz/bashtest) tool for 4 | testing your scripts. 5 | 6 | ### Write simple util 7 | 8 | We have a simple **stat.sh** script: 9 | 10 | #!/usr/bin/env bash 11 | 12 | if [ -z "$1" ] 13 | then 14 | DIR=./ 15 | else 16 | DIR=$1 17 | fi 18 | 19 | echo "Evaluate *.py statistics" 20 | FILES=$(find $DIR -name '*.py' | wc -l) 21 | LINES=$((find $DIR -name '*.py' -print0 | xargs -0 cat) | wc -l) 22 | echo "PYTHON FILES: $FILES" 23 | echo "PYTHON LINES: $LINES" 24 | 25 | This script evaluate the number of python files and the number of python 26 | code lines in the files. We can use it like **`./stat.sh `** 27 | 28 | ### Create testsuit 29 | 30 | Then make test suits for **stat.sh**. We make a directory **testsuit** 31 | which contain test python files. 32 | 33 | **testsuit/main.py** 34 | 35 | import foo 36 | print(foo) 37 | 38 | **testsuit/foo.py** 39 | 40 | BAR = 1 41 | BUZ = BAR + 2 42 | 43 | Ok! Our test suit is ready! We have 2 python files which contains 4 44 | lines of code. 45 | 46 | ### Write bashtests 47 | 48 | Lets write tests. We just write a shell command for testing our work. 49 | 50 | Create file **tests.bashtest**: 51 | 52 | $ ./stat.sh testsuit/ 53 | Evaluate *.py statistics 54 | PYTHON FILES: 2 55 | PYTHON LINES: 4 56 | 57 | This is our test! This is simple. Try to run it. 58 | 59 | # install bashtest if required! 60 | $ pip install bashtest 61 | 62 | # run tests 63 | $ bashtest *.bashtest 64 | 1 items passed all tests: 65 | 1 tests in tests.bashtest 66 | 1 tests in 1 items. 67 | 1 passed and 0 failed. 68 | Test passed. 69 | 70 | Thats all. We wrote one test. You can write more tests if you want. 71 | 72 | $ ls testsuit/ 73 | foo.py main.py 74 | 75 | $ ./stat.sh testsuit/ 76 | Evaluate *.py statistics 77 | PYTHON FILES: 2 78 | PYTHON LINES: 4 79 | 80 | And run tests again: 81 | 82 | $ bashtest *.bashtest 83 | 1 items passed all tests: 84 | 2 tests in tests.bashtest 85 | 2 tests in 1 items. 86 | 2 passed and 0 failed. 87 | Test passed. 88 | 89 | You can find more **.bashtest** examples in the [bashtest github 90 | repo](https://github.com/pahaz/bashtest). You can also write your 91 | question or report a bug 92 | [here](https://github.com/pahaz/bashtest/issues). 93 | 94 | Happy testing! 95 | -------------------------------------------------------------------------------- /original_source/snipplets/wrapperargs.txt: -------------------------------------------------------------------------------- 1 | ====== Generate code with own arguments properly quoted ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags: arguments, quoting, escaping, wrapper 5 | LastUpdate_dt: 2010-07-31 6 | Contributors: Jan Schampera 7 | type: snipplet 8 | ---- 9 | 10 | ^ Keywords: | arguments,escape,quote,wrapper,generate | 11 | ^ Contributor: | self | 12 | 13 | There are situations where Bash code needs to generate Bash code. A script that writes out another script the user or cron may start, for example. 14 | 15 | The general issue is easy, just write out text to the file. 16 | 17 | A specific detail of it is tricky: If the generated script needs to call a command using the arguments the first original script got, you have problem in writing out the correct code. 18 | 19 | I.e. if you run your generator script like 20 | ./myscript "give me 'some' water" 21 | then this script should generate code that looks like 22 | echo give me 'some' water" 23 | you need correct escapes or quotes to not generate shell special characters out of normal text (like embedded dollar signs ''$''). 24 | 25 | 26 | **__Solution:__** 27 | 28 | A loop over the own arguments that writes out properly quoted/escaped code to the generated script file 29 | 30 | There are two (maybe more) easy options: 31 | * writing out singlequoted strings and handle the embedded singlequotes 32 | * the [[commands:builtin:printf | printf command]] knows the ''%q'' format specification, which will print a string (like ''%s'' does), but with all shell special characters escaped 33 | 34 | ===== Using singlequoted string ===== 35 | 36 | 37 | #!/bin/bash 38 | 39 | # first option: 40 | # generate singlequoted strings out of your own arguments and handle embedded singlequotes 41 | # here to call 'echo' in the generated script 42 | 43 | { 44 | printf "#!/bin/bash\n\n" 45 | printf "echo " 46 | for arg; do 47 | arg=${arg/\'/\'\\\'\'} 48 | printf "'%s' " "${arg}" 49 | done 50 | 51 | printf "\n" 52 | } >s2 53 | 54 | 55 | The generated script will look like: 56 | 57 | 58 | #!/bin/bash 59 | 60 | echo 'fir$t' 'seco "ond"' 'thir'\''d' 61 | 62 | 63 | ===== Using printf ===== 64 | 65 | The second method is easier, though more or less Bash-only (due to the ''%q'' in printf): 66 | 67 | 68 | #!/bin/bash 69 | 70 | { 71 | printf "#!/bin/bash\n\n" 72 | printf "echo " 73 | for arg; do 74 | printf '%q ' "$arg" 75 | done 76 | 77 | printf "\n" 78 | } >s2 79 | 80 | 81 | The generated script will look like: 82 | 83 | 84 | #!/bin/bash 85 | 86 | echo fir\$t seco\ \"ond\" thir\'d 87 | 88 | -------------------------------------------------------------------------------- /original_source/commands/builtin/caller.txt: -------------------------------------------------------------------------------- 1 | ====== The caller builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | caller [FRAMENUMBER] 5 | 6 | ===== Description ===== 7 | The ''caller'' builtin command is used to print execution frames of subroutine calls. Without giving a framenumber, the topmost execution frame information is printed ("who called me") wile linenumber and filename. 8 | 9 | When an execution frame number is given (0 - topmost), the linenumber, the subroutine (function) and the filename is printed. When an invalid execution frame number is given, it exists ''FALSE''. This way it can be used in a loop (see the examples section below). 10 | 11 | ===== Examples ===== 12 | 13 | ==== Simple stack trace ==== 14 | 15 | The code below defines a function ''die'' that is used to exit the program. It prints a list of execution frames, starting with the topmost frame (0). The topmost frame is the "caller of the die function", in this case function "f1". 16 | 17 | This way, you can print a "stack trace" for debugging or logging purposes. 18 | 19 | The code is made very simple, just to show the basic purposes. 20 | 21 | 22 | #!/bin/bash 23 | 24 | die() { 25 | local frame=0 26 | while caller $frame; do 27 | ((++frame)); 28 | done 29 | echo "$*" 30 | exit 1 31 | } 32 | 33 | f1() { die "*** an error occured ***"; } 34 | f2() { f1; } 35 | f3() { f2; } 36 | 37 | f3 38 | 39 | 40 | **Output** 41 | 42 | 12 f1 ./callertest.sh 43 | 13 f2 ./callertest.sh 44 | 14 f3 ./callertest.sh 45 | 16 main ./callertest.sh 46 | *** an error occured *** 47 | 48 | 49 | ===== Notes ===== 50 | * ''caller'' produces no output unless used within a script that's run from a real file. It isn't particularly useful for interactive use, but can be used to create a decent ''die'' function to track down errors in moderately complex scripts. { bash /dev/stdin; } <<<$'f(){ g; }\ng(){ h; }\nh(){ while caller $((n++)); do :; done; }\nf' 51 | * For more sophisticated debugging, Bash extended debugging features are available and a number of special parameters that give more detail than caller (e.g. BASH_ARG{C,V}). Tools such as [[ http://bashdb.sourceforge.net/|Bashdb ]] can assist in using some of Bash's more advanced debug features. 52 | * The Bash manpage and help text specifies that the argument to ''caller'' is an "expr" (whatever that means). Only an integer is actually allowed, with no special interpretation of an "expression" as far as we can tell. 53 | 54 | ===== Portability considerations ===== 55 | * ''caller'' is not specified by POSIX(R) 56 | * the ''caller'' builtin command appeared in Bash version 3.0 57 | 58 | ===== See also ===== -------------------------------------------------------------------------------- /docs/commands/builtin/caller.md: -------------------------------------------------------------------------------- 1 | # The caller builtin command 2 | 3 | ## Synopsis 4 | 5 | caller [FRAMENUMBER] 6 | 7 | ## Description 8 | 9 | The `caller` builtin command is used to print execution frames of 10 | subroutine calls. Without giving a framenumber, the topmost execution 11 | frame information is printed ("who called me") wile linenumber and 12 | filename. 13 | 14 | When an execution frame number is given (0 - topmost), the linenumber, 15 | the subroutine (function) and the filename is printed. When an invalid 16 | execution frame number is given, it exists `FALSE`. This way it can be 17 | used in a loop (see the examples section below). 18 | 19 | ## Examples 20 | 21 | ### Simple stack trace 22 | 23 | The code below defines a function `die` that is used to exit the 24 | program. It prints a list of execution frames, starting with the topmost 25 | frame (0). The topmost frame is the "caller of the die function", in 26 | this case function "f1". 27 | 28 | This way, you can print a "stack trace" for debugging or logging 29 | purposes. 30 | 31 | The code is made very simple, just to show the basic purposes. 32 | 33 | ``` bash 34 | #!/bin/bash 35 | 36 | die() { 37 | local frame=0 38 | while caller $frame; do 39 | ((++frame)); 40 | done 41 | echo "$*" 42 | exit 1 43 | } 44 | 45 | f1() { die "*** an error occured ***"; } 46 | f2() { f1; } 47 | f3() { f2; } 48 | 49 | f3 50 | ``` 51 | 52 | **Output** 53 | 54 | 12 f1 ./callertest.sh 55 | 13 f2 ./callertest.sh 56 | 14 f3 ./callertest.sh 57 | 16 main ./callertest.sh 58 | *** an error occured *** 59 | 60 | ## Notes 61 | 62 | - `caller` produces no output unless used within a script that's run 63 | from a real file. It isn't particularly useful for interactive use, 64 | but can be used to create a decent `die` function to track down 65 | errors in moderately complex scripts. 66 | `{ bash /dev/stdin; } <<<$'f(){ g; }\ng(){ h; }\nh(){ while caller $((n++)); do :; done; }\nf'` 67 | - For more sophisticated debugging, Bash extended debugging features 68 | are available and a number of special parameters that give more 69 | detail than caller (e.g. BASH_ARG{C,V}). Tools such as 70 | [Bashdb](http://bashdb.sourceforge.net/) can assist in using some of 71 | Bash's more advanced debug features. 72 | - The Bash manpage and help text specifies that the argument to 73 | `caller` is an "expr" (whatever that means). Only an integer is 74 | actually allowed, with no special interpretation of an 75 | "expression" as far as we can tell. 76 | 77 | ## Portability considerations 78 | 79 | - `caller` is not specified by POSIX(R) 80 | - the `caller` builtin command appeared in Bash version 3.0 81 | 82 | ## See also 83 | -------------------------------------------------------------------------------- /original_source/howto/testing-your-scripts.txt: -------------------------------------------------------------------------------- 1 | The one of the simplest way to check your bash/sh scripts is run it and check it output or run it and check the result. This tutorial shows how-to use [[https://github.com/pahaz/bashtest|bashtest]] tool for testing your scripts. 2 | 3 | ==== Write simple util ==== 4 | 5 | We have a simple **stat.sh** script: 6 | 7 | 8 | #!/usr/bin/env bash 9 | 10 | if [ -z "$1" ] 11 | then 12 | DIR=./ 13 | else 14 | DIR=$1 15 | fi 16 | 17 | echo "Evaluate *.py statistics" 18 | FILES=$(find $DIR -name '*.py' | wc -l) 19 | LINES=$((find $DIR -name '*.py' -print0 | xargs -0 cat) | wc -l) 20 | echo "PYTHON FILES: $FILES" 21 | echo "PYTHON LINES: $LINES" 22 | 23 | 24 | This script evaluate the number of python files and the number of python code lines in the files. 25 | We can use it like **./stat.sh ** 26 | 27 | ==== Create testsuit ==== 28 | 29 | Then make test suits for **stat.sh**. We make a directory **testsuit** which contain test python files. 30 | 31 | **testsuit/main.py** 32 | 33 | import foo 34 | print(foo) 35 | 36 | 37 | **testsuit/foo.py** 38 | 39 | BAR = 1 40 | BUZ = BAR + 2 41 | 42 | 43 | Ok! Our test suit is ready! 44 | We have 2 python files which contains 4 lines of code. 45 | 46 | ==== Write bashtests ==== 47 | 48 | Lets write tests. We just write a shell command for testing our work. 49 | 50 | Create file **tests.bashtest**: 51 | 52 | 53 | $ ./stat.sh testsuit/ 54 | Evaluate *.py statistics 55 | PYTHON FILES: 2 56 | PYTHON LINES: 4 57 | 58 | 59 | 60 | This is our test! This is simple. Try to run it. 61 | 62 | 63 | # install bashtest if required! 64 | $ pip install bashtest 65 | 66 | 67 | 68 | # run tests 69 | $ bashtest *.bashtest 70 | 1 items passed all tests: 71 | 1 tests in tests.bashtest 72 | 1 tests in 1 items. 73 | 1 passed and 0 failed. 74 | Test passed. 75 | 76 | 77 | Thats all. We wrote one test. You can write more tests if you want. 78 | 79 | 80 | $ ls testsuit/ 81 | foo.py main.py 82 | 83 | $ ./stat.sh testsuit/ 84 | Evaluate *.py statistics 85 | PYTHON FILES: 2 86 | PYTHON LINES: 4 87 | 88 | 89 | 90 | And run tests again: 91 | 92 | 93 | $ bashtest *.bashtest 94 | 1 items passed all tests: 95 | 2 tests in tests.bashtest 96 | 2 tests in 1 items. 97 | 2 passed and 0 failed. 98 | Test passed. 99 | 100 | 101 | You can find more **.bashtest** examples in the [[https://github.com/pahaz/bashtest | bashtest github repo]]. You can also write your question or report a bug [[https://github.com/pahaz/bashtest/issues | here]]. 102 | 103 | Happy testing! 104 | -------------------------------------------------------------------------------- /docs/misc/readthesourceluke.md: -------------------------------------------------------------------------------- 1 | Comments extracted from the bash source and therefore Copyright (C) 2 | 1987-2004 Free Software Foundation, Inc. under the terms of the GNU 3 | General Public License etc.. 4 | 5 | from `mailcheck.c`: 6 | 7 | ``` C 8 | /* check_mail () is useful for more than just checking mail. Since it has 9 | the paranoids dream ability of telling you when someone has read your 10 | mail, it can just as easily be used to tell you when someones .profile 11 | file has been read, thus letting one know when someone else has logged 12 | in. Pretty good, huh? */ 13 | ``` 14 | 15 | From `builtins/read.def`: 16 | 17 | ``` C 18 | /* If there are no variables, save the text of the line read to the 19 | variable $REPLY. ksh93 strips leading and trailing IFS whitespace, 20 | so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the 21 | same way, but I believe that the difference in behaviors is useful 22 | enough to not do it. Without the bash behavior, there is no way 23 | to read a line completely without interpretation or modification 24 | unless you mess with $IFS (e.g., setting it to the empty string). 25 | If you disagree, change the occurrences of `#if 0' to `#if 1' below. */ 26 | ``` 27 | 28 | from `variables.c`: 29 | 30 | ``` C 31 | /* 32 | * 24 October 2001 33 | * 34 | * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT 35 | * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in 36 | * isnetconn() to avoid running the startup files more often than wanted. 37 | * That will, of course, only work if the user's login shell is bash, so 38 | * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined 39 | * in config-top.h. 40 | */ 41 | ``` 42 | 43 | From `shell.h`: 44 | 45 | ``` C 46 | /* Values that can be returned by execute_command (). */ 47 | #define EXECUTION_FAILURE 1 48 | #define EXECUTION_SUCCESS 0 49 | 50 | /* Usage messages by builtins result in a return status of 2. */ 51 | #define EX_BADUSAGE 2 52 | 53 | /* Special exit statuses used by the shell, internally and externally. */ 54 | #define EX_RETRYFAIL 124 55 | #define EX_WEXPCOMSUB 125 56 | #define EX_BINARY_FILE 126 57 | #define EX_NOEXEC 126 58 | #define EX_NOINPUT 126 59 | #define EX_NOTFOUND 127 60 | 61 | #define EX_SHERRBASE 256 /* all special error values are > this. */ 62 | 63 | #define EX_BADSYNTAX 257 /* shell syntax error */ 64 | #define EX_USAGE 258 /* syntax error in usage */ 65 | #define EX_REDIRFAIL 259 /* redirection failed */ 66 | #define EX_BADASSIGN 260 /* variable assignment error */ 67 | #define EX_EXPFAIL 261 /* word expansion failed */ 68 | ``` 69 | -------------------------------------------------------------------------------- /original_source/syntax/ccmd/if_clause.txt: -------------------------------------------------------------------------------- 1 | ====== The if-clause ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | if ; then 6 | 7 | fi 8 | 9 | 10 | if ; then 11 | 12 | else 13 | 14 | fi 15 | 16 | 17 | if ; then 18 | 19 | elif ; then 20 | 21 | else 22 | 23 | fi 24 | 25 | 26 | ===== Description ===== 27 | The ''if''-clause can control the script's flow (what's executed) by looking at the exit codes of other commands. 28 | 29 | All commandsets '''' are interpreted as [[syntax:basicgrammar#lists | command lists]], thus they can contain the whole palette from [[syntax:basicgrammar#simple_commands | simple commands]] over [[syntax:basicgrammar#pipelines | pipelines]] to [[syntax:basicgrammar#compound_commands | compound commands]] (and their combination) as condition. 30 | 31 | ==== Operation ==== 32 | The **''if ''** commands are executed. If the exit code was 0 (TRUE) then the **''then ''** commands are executed, otherwise the **''elif ''** commands and their **''then ''** statements are executed in turn, if all down to the last one fails, the **''else ''** commands are executed, if one of the ''elif'' succeeds, its ''then'' thread is executed, and the ''if''-clause finishes. 33 | 34 | Basically, the ''elif'' clauses are just additional conditions to test (like a chain of conditions) if the very first condition failed. If one of the conditions fails, the ''else'' commands are executed, otherwise the commands of the condition that succeeded. 35 | 36 | 37 | ===== Examples ===== 38 | **Check if a specific user exists in /etc/passwd :-)** 39 | 40 | if grep ^myuser: /etc/passwd >/dev/null 2>&1; then 41 | echo "Yes, it seems I'm real" 42 | else 43 | echo "Uh - am I a ghost?" 44 | fi 45 | 46 | 47 | **Mount with check** 48 | 49 | if ! mount /mnt/backup >/dev/null 2>&1; then 50 | echo "FATAL: backup mount failed" >&2 51 | exit 1 52 | fi 53 | 54 | 55 | **Multiple commands as condition** 56 | 57 | It's perfectly valid to do: 58 | 59 | if echo "I'm testing!"; [ -e /some/file ]; then 60 | ... 61 | fi 62 | 63 | The exit code that dictates the condition's value is the exit code of the very last command executed in the condition-list (here: The ''[ -e /some/file ]'') 64 | 65 | **A complete pipe as condition** 66 | 67 | A complete pipe can also be used as condition. It's very similar to the example above (multiple commands): 68 | 69 | if echo "Hello world!" | grep -i hello >/dev/null 2>&1; then 70 | echo "You just said 'hello', yeah?" 71 | fi 72 | 73 | 74 | ===== Portability considerations ===== 75 | 76 | 77 | ===== See also ===== 78 | * Internal: [[commands:classictest | the classic test command]] 79 | -------------------------------------------------------------------------------- /original_source/misc/readthesourceluke.txt: -------------------------------------------------------------------------------- 1 | Comments extracted from the bash source and therefore Copyright (C) 1987-2004 Free Software Foundation, Inc. under 2 | the terms of the GNU General Public License etc.. 3 | 4 | from ''mailcheck.c'': 5 | 6 | /* check_mail () is useful for more than just checking mail. Since it has 7 | the paranoids dream ability of telling you when someone has read your 8 | mail, it can just as easily be used to tell you when someones .profile 9 | file has been read, thus letting one know when someone else has logged 10 | in. Pretty good, huh? */ 11 | 12 | 13 | From ''builtins/read.def'': 14 | 15 | 16 | /* If there are no variables, save the text of the line read to the 17 | variable $REPLY. ksh93 strips leading and trailing IFS whitespace, 18 | so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the 19 | same way, but I believe that the difference in behaviors is useful 20 | enough to not do it. Without the bash behavior, there is no way 21 | to read a line completely without interpretation or modification 22 | unless you mess with $IFS (e.g., setting it to the empty string). 23 | If you disagree, change the occurrences of `#if 0' to `#if 1' below. */ 24 | 25 | 26 | from ''variables.c'': 27 | 28 | /* 29 | * 24 October 2001 30 | * 31 | * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT 32 | * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in 33 | * isnetconn() to avoid running the startup files more often than wanted. 34 | * That will, of course, only work if the user's login shell is bash, so 35 | * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined 36 | * in config-top.h. 37 | */ 38 | 39 | 40 | From ''shell.h'': 41 | 42 | /* Values that can be returned by execute_command (). */ 43 | #define EXECUTION_FAILURE 1 44 | #define EXECUTION_SUCCESS 0 45 | 46 | /* Usage messages by builtins result in a return status of 2. */ 47 | #define EX_BADUSAGE 2 48 | 49 | /* Special exit statuses used by the shell, internally and externally. */ 50 | #define EX_RETRYFAIL 124 51 | #define EX_WEXPCOMSUB 125 52 | #define EX_BINARY_FILE 126 53 | #define EX_NOEXEC 126 54 | #define EX_NOINPUT 126 55 | #define EX_NOTFOUND 127 56 | 57 | #define EX_SHERRBASE 256 /* all special error values are > this. */ 58 | 59 | #define EX_BADSYNTAX 257 /* shell syntax error */ 60 | #define EX_USAGE 258 /* syntax error in usage */ 61 | #define EX_REDIRFAIL 259 /* redirection failed */ 62 | #define EX_BADASSIGN 260 /* variable assignment error */ 63 | #define EX_EXPFAIL 261 /* word expansion failed */ 64 | 65 | 66 | -------------------------------------------------------------------------------- /docs/syntax/ccmd/if_clause.md: -------------------------------------------------------------------------------- 1 | # The if-clause 2 | 3 | ## Synopsis 4 | 5 | if ; then 6 | 7 | fi 8 | 9 | if ; then 10 | 11 | else 12 | 13 | fi 14 | 15 | if ; then 16 | 17 | elif ; then 18 | 19 | else 20 | 21 | fi 22 | 23 | ## Description 24 | 25 | The `if`-clause can control the script's flow (what's executed) by 26 | looking at the exit codes of other commands. 27 | 28 | All commandsets `` are interpreted as [command 29 | lists](../../syntax/basicgrammar.md#lists), thus they can contain the whole 30 | palette from [simple commands](../../syntax/basicgrammar.md#simple_commands) 31 | over [pipelines](../../syntax/basicgrammar.md#pipelines) to [compound 32 | commands](../../syntax/basicgrammar.md#compound_commands) (and their 33 | combination) as condition. 34 | 35 | ### Operation 36 | 37 | The **`if `** commands are executed. If the exit code was 0 (TRUE) 38 | then the **`then `** commands are executed, otherwise the 39 | **`elif `** commands and their **`then `** statements are 40 | executed in turn, if all down to the last one fails, the 41 | **`else `** commands are executed, if one of the `elif` succeeds, 42 | its `then` thread is executed, and the `if`-clause finishes. 43 | 44 | Basically, the `elif` clauses are just additional conditions to test 45 | (like a chain of conditions) if the very first condition failed. If one 46 | of the conditions fails, the `else` commands are executed, otherwise the 47 | commands of the condition that succeeded. 48 | 49 | ## Examples 50 | 51 | **Check if a specific user exists in /etc/passwd :-)** 52 | 53 | if grep ^myuser: /etc/passwd >/dev/null 2>&1; then 54 | echo "Yes, it seems I'm real" 55 | else 56 | echo "Uh - am I a ghost?" 57 | fi 58 | 59 | **Mount with check** 60 | 61 | if ! mount /mnt/backup >/dev/null 2>&1; then 62 | echo "FATAL: backup mount failed" >&2 63 | exit 1 64 | fi 65 | 66 | **Multiple commands as condition** 67 | 68 | It's perfectly valid to do: 69 | 70 | if echo "I'm testing!"; [ -e /some/file ]; then 71 | ... 72 | fi 73 | 74 | The exit code that dictates the condition's value is the exit code of 75 | the very last command executed in the condition-list (here: The 76 | `[ -e /some/file ]`) 77 | 78 | **A complete pipe as condition** 79 | 80 | A complete pipe can also be used as condition. It's very similar to the 81 | example above (multiple commands): 82 | 83 | if echo "Hello world!" | grep -i hello >/dev/null 2>&1; then 84 | echo "You just said 'hello', yeah?" 85 | fi 86 | 87 | ## Portability considerations 88 | 89 | ## See also 90 | 91 | - Internal: [the classic test command](../../commands/classictest.md) 92 | -------------------------------------------------------------------------------- /original_source/syntax/expansion/arith.txt: -------------------------------------------------------------------------------- 1 | ====== Arithmetic expansion ====== 2 | 3 | 4 | $(( )) 5 | 6 | $[ ] 7 | 8 | 9 | The [[syntax:arith_expr | arithmetic expression]] '''' is evaluated and expands to the result. The output of the arithmetic expansion is guaranteed to be one word and a digit in Bash. 10 | 11 | Please **do not use the second form ''$[ ... ]''**! It's deprecated. The preferred and standardized form is ''$(( ... ))''! 12 | 13 | Example 14 | 15 | function printSum { 16 | typeset -A args 17 | typeset name 18 | for name in first second; do 19 | [[ -t 0 ]] && printf 'Enter %s positive integer: ' "$name" >&2 20 | read -r ${BASH_VERSION+-e} "args[$name]" 21 | [[ ${args[$name]} == +([[:digit:]]) ]] || return 1 # Validation is extremely important whenever user input is used in arithmetic. 22 | done 23 | printf 'The sum is %d.' $((${args[first]} + ${args[second]})) 24 | } 25 | 26 | 27 | **Note** that in Bash you don't need the arithmetic expansion to check for the boolean value of an arithmetic expression. This can be done using the [[syntax:ccmd:arithmetic_eval | arithmetic evaluation compound command]]: 28 | 29 | 30 | printf %s 'Enter a number: ' >&2 31 | read -r number 32 | if ((number == 1234)); then 33 | echo 'Good guess' 34 | else 35 | echo 'Haha... :-P' 36 | fi 37 | 38 | 39 | **Variables** used inside the arithmetic expansion, as in all arithmetic contexts, can be used with or without variable expansion: 40 | 41 | 42 | x=1 43 | 44 | echo $((x)) # Good. 45 | echo $(($x)) # Ok. Avoid expansions within arithmetic. Use variables directly. 46 | echo $(("$x")) # Error. There is no quote-removal in arithmetic contexts. It expands to $(("1")), which is an invalid arithmetic expression. 47 | echo $((x[0])) # Good. 48 | echo $((${x[0]})) # Ok. Nested expansion again. 49 | echo $((${x[$((${x[!$x]}-$x))]})) # Same as above but more ridiculous. 50 | echo $(($x[0])) # Error. This expands to $((1[0])), an invalid expression. 51 | 52 | 53 | ===== Bugs and Portability considerations ===== 54 | * The original Bourne shell doesn't have arithmetic expansions. You have to use something like ''expr(1)'' within backticks instead. Since ''expr'' is horrible (as are backticks), and arithmetic expansion is required by POSIX, you should not worry about this, and preferably fix any code you find that's still using ''expr''. 55 | 56 | ===== See also ===== 57 | * [[syntax:arith_expr | arithmetic expressions]] 58 | * [[syntax:ccmd:arithmetic_eval | arithmetic evaluation compound command]] 59 | * [[syntax:expansion:intro | Introduction to expansion and substitution]] 60 | * [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04 | POSIX definition]] 61 | -------------------------------------------------------------------------------- /docs/syntax/expansion/arith.md: -------------------------------------------------------------------------------- 1 | # Arithmetic expansion 2 | 3 | $(( )) 4 | 5 | $[ ] 6 | 7 | The [arithmetic expression](../../syntax/arith_expr.md) `` is 8 | evaluated and expands to the result. The output of the arithmetic 9 | expansion is guaranteed to be one word and a digit in Bash. 10 | 11 | Please **do not use the second form `$[ ... ]`**! It's deprecated. The 12 | preferred and standardized form is `$(( ... ))`! 13 | 14 | Example 15 | 16 | ``` bash 17 | function printSum { 18 | typeset -A args 19 | typeset name 20 | for name in first second; do 21 | [[ -t 0 ]] && printf 'Enter %s positive integer: ' "$name" >&2 22 | read -r ${BASH_VERSION+-e} "args[$name]" 23 | [[ ${args[$name]} == +([[:digit:]]) ]] || return 1 # Validation is extremely important whenever user input is used in arithmetic. 24 | done 25 | printf 'The sum is %d.' $((${args[first]} + ${args[second]})) 26 | } 27 | ``` 28 | 29 | **Note** that in Bash you don't need the arithmetic expansion to check 30 | for the boolean value of an arithmetic expression. This can be done 31 | using the [arithmetic evaluation compound 32 | command](../../syntax/ccmd/arithmetic_eval.md): 33 | 34 | ``` bash 35 | printf %s 'Enter a number: ' >&2 36 | read -r number 37 | if ((number == 1234)); then 38 | echo 'Good guess' 39 | else 40 | echo 'Haha... :-P' 41 | fi 42 | ``` 43 | 44 | **Variables** used inside the arithmetic expansion, as in all arithmetic 45 | contexts, can be used with or without variable expansion: 46 | 47 | ``` bash 48 | x=1 49 | 50 | echo $((x)) # Good. 51 | echo $(($x)) # Ok. Avoid expansions within arithmetic. Use variables directly. 52 | echo $(("$x")) # Error. There is no quote-removal in arithmetic contexts. It expands to $(("1")), which is an invalid arithmetic expression. 53 | echo $((x[0])) # Good. 54 | echo $((${x[0]})) # Ok. Nested expansion again. 55 | echo $((${x[$((${x[!$x]}-$x))]})) # Same as above but more ridiculous. 56 | echo $(($x[0])) # Error. This expands to $((1[0])), an invalid expression. 57 | ``` 58 | 59 | ## Bugs and Portability considerations 60 | 61 | - The original Bourne shell doesn't have arithmetic expansions. You 62 | have to use something like `expr(1)` within backticks instead. Since 63 | `expr` is horrible (as are backticks), and arithmetic expansion is 64 | required by POSIX, you should not worry about this, and preferably 65 | fix any code you find that's still using `expr`. 66 | 67 | ## See also 68 | 69 | - [arithmetic expressions](../../syntax/arith_expr.md) 70 | - [arithmetic evaluation compound 71 | command](../../syntax/ccmd/arithmetic_eval.md) 72 | - [Introduction to expansion and 73 | substitution](../../syntax/expansion/intro.md) 74 | - [POSIX 75 | definition](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04) 76 | -------------------------------------------------------------------------------- /original_source/commands/builtin/shift.txt: -------------------------------------------------------------------------------- 1 | ====== The shift builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | shift [n] 5 | 6 | ===== Description ===== 7 | 8 | The ''shift'' builtin command is used to "shift" the positional parameters by the given number ''n'' or by 1, if no number is given. 9 | 10 | This means, the number and the position of the positional parameters are changed. 11 | The very first positional parameter is discarded, the second becomes the first one, etc. 12 | 13 | Imagine the following set of positional parameters (''$1'' to ''$4''): 14 | 15 | ^1 |This | 16 | ^2 |is | 17 | ^3 |a | 18 | ^4 |test | 19 | 20 | When you use ''shift 1'', they will be changed to: 21 | 22 | ^1 |is | 23 | ^2 |a | 24 | ^3 |test | 25 | 26 | The [[syntax:shellvars#special_parameters|special parameter]] ''$#'' will reflect the final number of positional parameters. 27 | 28 | If the number given is 0, no changes are made to the positional parameters. 29 | 30 | 31 | ==== Options ==== 32 | 33 | There are no options. 34 | 35 | ==== Return status ==== 36 | 37 | ^Status ^Reason ^ 38 | |0 |no error | 39 | |1 |non-numeric argument | 40 | |1 |given number (or the default 1) is bigger than the number of actually present positional parameters | 41 | |1 |given number is negative | 42 | 43 | 44 | ===== Examples ===== 45 | 46 | ===== Portability considerations ===== 47 | 48 | * The ''shift'' builtin command is specified by POSIX(r). 49 | * Many shells will throw a fatal error when attempting to ''shift'' more than the number of positional parameters. **POSIX does not require that behavior**. Bash (even in POSIX mode) and Zsh return 1 when there are no args, and no error output is produced unless the [[internals/shell_options#shift_verbose | shift_verbose]] [[commands/builtin/shopt | shopt]] option is enabled. Ksh93, pdksh, posh, mksh, and dash, all throw useless fatal shell errors. 50 | $ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f' 51 | dash: 1: shift: can't shift that many 52 | In most shells, you can work around this problem using the [[commands:builtin:command | command]] builtin to suppress fatal errors caused by //special builtins//. $ dash -c 'f() { if command shift 2>/dev/null; then echo "$1"; else echo "no args"; fi; }; f' 53 | no args 54 | While, POSIX requires this behavior, it isn't very obvious and some shells don't do it correctly. To work around this, you can use something like: 55 | 56 | $ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f' 57 | no args 58 | 59 | The mksh maintainer refuses to change either the ''shift'' or ''command'' builtins. [[https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa | Fixed]]. (Thanks!) 60 | * Perhaps almost as bad as the above, busybox sh's ''shift'' always returns success, even when attempting to shift beyond the final argument. $ bb -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f' 61 | (no output) 62 | The above mksh workaround will work in this case too. 63 | 64 | ===== See also ===== 65 | 66 | -------------------------------------------------------------------------------- /original_source/howto/collapsing_functions.txt: -------------------------------------------------------------------------------- 1 | ====== Collapsing Functions ====== 2 | 3 | {{keywords>bash shell scripting example function collapse}} 4 | 5 | ===== What is a "Collapsing Function"? ===== 6 | A collapsing function is a function whose behavior changes depending upon the circumstances under which it's run. Function collapsing is useful when you find yourself repeatedly checking a variable whose value never changes. 7 | 8 | ===== How do I make a function collapse? ===== 9 | Function collapsing requires some static feature in the environment. A common example is a script that gives the user the option of having "verbose" output. 10 | 11 | #!/bin/bash 12 | 13 | [[ $1 = -v || $1 = --verbose ]] && verbose=1 14 | 15 | chatter() { 16 | if [[ $verbose ]]; then 17 | chatter() { 18 | echo "$@" 19 | } 20 | chatter "$@" 21 | else 22 | chatter() { 23 | : 24 | } 25 | fi 26 | } 27 | 28 | echo "Waiting for 10 seconds." 29 | for i in {1..10}; do 30 | chatter "$i" 31 | sleep 1 32 | done 33 | 34 | 35 | ===== How does it work? ===== 36 | The first time you run chatter(), the function redefines itself based on the value of verbose. Thereafter, chatter doesn't check $verbose, it simply is. Further calls to the function reflect its collapsed nature. If verbose is unset, chatter will echo nothing, with no extra effort from the developer. 37 | ===== More examples ===== 38 | FIXME Add more examples! 39 | 40 | # Somewhat more portable find -executable 41 | # FIXME/UNTESTED (I don't have access to all of the different versions of find.) 42 | # Usage: find PATH ARGS -- use find like normal, except use -executable instead of 43 | # various versions of -perm /+ blah blah and hacks 44 | find() { 45 | hash find || { echo 'find not found!'; exit 1; } 46 | # We can be pretty sure "$0" should be executable. 47 | if [[ $(command find "$0" -executable 2> /dev/null) ]]; then 48 | unset -f find # We can just use the command find 49 | elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then 50 | find() { 51 | typeset arg args 52 | for arg do 53 | [[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg") 54 | done 55 | command find "${args[@]}" 56 | } 57 | elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then 58 | find() { 59 | typeset arg args 60 | for arg do 61 | [[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg") 62 | done 63 | command find "${args[@]}" 64 | } 65 | else # Last resort 66 | find() { 67 | typeset arg args 68 | for arg do 69 | [[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg") 70 | done 71 | command find "${args[@]}" 72 | } 73 | fi 74 | find "$@" 75 | } 76 | 77 | 78 | 79 | #!/bin/bash 80 | # Using collapsing functions to turn debug messages on/off 81 | 82 | [ "--debug" = "$1" ] && dbg=echo || dbg=: 83 | 84 | 85 | # From now on if you use $dbg instead of echo, you can select if messages will be shown 86 | 87 | $dbg "This message will only be displayed if --debug is specified at the command line 88 | 89 | -------------------------------------------------------------------------------- /docs/commands/builtin/shift.md: -------------------------------------------------------------------------------- 1 | # The shift builtin command 2 | 3 | ## Synopsis 4 | 5 | shift [n] 6 | 7 | ## Description 8 | 9 | The `shift` builtin command is used to "shift" the positional 10 | parameters by the given number `n` or by 1, if no number is given. 11 | 12 | This means, the number and the position of the positional parameters are 13 | changed. The very first positional parameter is discarded, the second 14 | becomes the first one, etc. 15 | 16 | Imagine the following set of positional parameters (`$1` to `$4`): 17 | 18 | |Positional Parameter|Value| 19 | |-|-| 20 | |1|This 21 | |2|is| 22 | |3|a| 23 | |4|test| 24 | 25 | When you use `shift 1`, they will be changed to: 26 | 27 | |Positional Parameter|Value| 28 | |-|-| 29 | |1|is| 30 | |2|a| 31 | |3|test| 32 | 33 | The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will 34 | reflect the final number of positional parameters. 35 | 36 | If the number given is 0, no changes are made to the positional 37 | parameters. 38 | 39 | ### Options 40 | 41 | There are no options. 42 | 43 | ### Return status 44 | 45 | |Status|Reason| 46 | |------|------| 47 | |0|no error| 48 | |1|non-numeric argument| 49 | |1|given number (or the default 1) is bigger than the number of actually present positional parameters| 50 | |1|given number is negative| 51 | 52 | ## Examples 53 | 54 | ## Portability considerations 55 | 56 | - The `shift` builtin command is specified by POSIX(r). 57 | - Many shells will throw a fatal error when attempting to `shift` more 58 | than the number of positional parameters. **POSIX does not require 59 | that behavior**. Bash (even in POSIX mode) and Zsh return 1 when 60 | there are no args, and no error output is produced unless the 61 | [shift_verbose](../../internals/shell_options.md#shift_verbose) 62 | [shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh, 63 | posh, mksh, and dash, all throw useless fatal shell 64 | errors. 65 | ``` 66 | $ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f' 67 | dash: 1: shift: can't shift that many 68 | ``` 69 | In most shells, you can work around this problem using the 70 | `command` builtin to suppress fatal 71 | errors caused by *special builtins*. 72 | ``` 73 | $ dash -c 'f() { if command shift 2>/dev/null; then echo "$1"; else echo "no args"; fi; }; f' 74 | no args 75 | ``` 76 | While, POSIX requires this behavior, it isn't very 77 | obvious and some shells don't do it correctly. To work around this, you 78 | can use something like: 79 | ``` 80 | $ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f' 81 | no args 82 | ``` 83 | The mksh maintainer refuses to change either the `shift` or `command` builtins. 84 | [Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa). 85 | (Thanks!) 86 | 87 | - Perhaps almost as bad as the above, busybox sh's `shift` always 88 | returns success, even when attempting to shift beyond the final 89 | argument. 90 | ``` 91 | $ bb -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f' 92 | (no output) 93 | ``` 94 | The above mksh workaround will work in this case 95 | too. 96 | 97 | ## See also 98 | -------------------------------------------------------------------------------- /original_source/syntax/expansion/tilde.txt: -------------------------------------------------------------------------------- 1 | ====== Tilde expansion ====== 2 | 3 | {{keywords>bash shell scripting expansion substitution tilde home homedir shortcut}} 4 | 5 | 6 | ~ 7 | ~/... 8 | 9 | ~NAME 10 | ~NAME/... 11 | 12 | ~+ 13 | ~+/... 14 | 15 | ~- 16 | ~-/... 17 | 18 | 19 | The tilde expansion is used to expand to several specific pathnames: 20 | * home directories 21 | * current working directory 22 | * previous working directory 23 | 24 | Tilde expansion is only performed, when the tilde-construct is at the beginning of a word, or a separate word. 25 | 26 | If there's nothing to expand, i.e., in case of a wrong username or any other error condition, the tilde construct is not replaced, it stays what it is. 27 | 28 | Tilde expansion is also performed everytime a variable is assigned: 29 | * after the **first** ''='': ''TARGET=~moonman/share'' 30 | * after **every** '':'' (colon) in the assigned value: ''TARGET=file:~moonman/share'' 31 | 32 | 33 | As of now (Bash 4.3-alpha) the following constructs **also** works, though it's not a variable assignment: 34 | 35 | echo foo=~ 36 | echo foo=:~ 37 | 38 | I don't know yet, if this is a bug or intended. 39 | 40 | 41 | This way you can correctly use the tilde expansion in your [[syntax:shellvars#PATH|PATH]]: 42 | 43 | PATH=~/mybins:~peter/mybins:$PATH 44 | 45 | 46 | **Spaces in the referenced pathes?** A construct like... 47 | 48 | ~/"my directory" 49 | 50 | ...is perfectly valid and works! 51 | 52 | ===== Home directory ===== 53 | 54 | ~ 55 | ~ 56 | 57 | 58 | This form expands to the home-directory of the current user (''~'') or the home directory of the given user (''~''). 59 | 60 | If the given user doesn't exist (or if his home directory isn't determinable, for some reason), it doesn't expand to something else, it stays what it is. The requested home directory is found by asking the operating system for the associated home directory for ''''. 61 | 62 | To find the home directory of the current user (''~''), Bash has a precedence: 63 | * expand to the value of [[syntax:shellvars#HOME|HOME]] if it's defined 64 | * expand to the home directory of the user executing the shell (operating system) 65 | That means, the variable ''HOME'' can override the "real" home directory, at least regarding tilde expansion. 66 | 67 | 68 | ===== Current working directory ===== 69 | 70 | ~+ 71 | 72 | 73 | This expands to the value of the [[syntax:shellvars#PWD|PWD]] variable, which holds the currect working directory: 74 | 75 | echo "CWD is $PWD" 76 | 77 | is equivalent to (note it **must** be a separate word!): 78 | 79 | echo "CWD is" ~+ 80 | 81 | 82 | 83 | ===== Previous working directory ===== 84 | 85 | 86 | ~- 87 | 88 | 89 | This expands to the value of the [[syntax:shellvars#OLDPWD|OLDPWD]] variable, which holds the previous working directory (the one before the last ''cd''). If ''OLDPWD'' is unset (never changed the directory), it is not expanded. 90 | 91 | 92 | $ pwd 93 | /home/bash 94 | $ cd /etc 95 | $ echo ~- 96 | /home/bash 97 | 98 | 99 | 100 | ===== See also ===== 101 | * Internal: [[syntax:expansion:intro | Introduction to expansion and substitution]] 102 | -------------------------------------------------------------------------------- /original_source/snipplets/add_color_to_your_scripts.txt: -------------------------------------------------------------------------------- 1 | ====== Add Color to your scripts ====== 2 | 3 | ---- dataentry snipplet ---- 4 | snipplet_tags : terminal, color 5 | LastUpdate_dt : 2013-03-23 6 | Contributors : Frank Lazzarini, Dan Douglas 7 | type : snipplet 8 | ---- 9 | 10 | Make your scripts output more readable using bash colors. Simply add these variables to your script, and you will be able to echo in color. (I haven't added all the colors available, just some basics) 11 | 12 | 13 | # Colors 14 | ESC_SEQ="\x1b[" 15 | COL_RESET=$ESC_SEQ"39;49;00m" 16 | COL_RED=$ESC_SEQ"31;01m" 17 | COL_GREEN=$ESC_SEQ"32;01m" 18 | COL_YELLOW=$ESC_SEQ"33;01m" 19 | COL_BLUE=$ESC_SEQ"34;01m" 20 | COL_MAGENTA=$ESC_SEQ"35;01m" 21 | COL_CYAN=$ESC_SEQ"36;01m" 22 | 23 | 24 | 25 | Now if you want to output some text in color use //echo -e// instead of just echo. And always remember to use the //$COL_RESET// variable to reset the color changes in bash. Like so .... 26 | 27 | 28 | echo -e "$COL_RED This is red $COL_RESET" 29 | echo -e "$COL_BLUE This is blue $COL_RESET" 30 | echo -e "$COL_YELLOW This is yellow $COL_RESET" 31 | 32 | 33 | 34 | But also see the notes in [[scripting:terminalcodes | the article about using terminalcodes]] about generating codes and hardwiring codes. 35 | 36 | This snipplet sets up associative arrays for basic color codes using ''tput'' for Bash, ksh93 or zsh. You can pass it variable names to correspond with a collection of codes. There's a ''main'' function with example usage. 37 | 38 | #!/usr/bin/env bash 39 | 40 | ${ZSH_VERSION+false} || emulate ksh 41 | ${BASH_VERSION+shopt -s lastpipe extglob} 42 | 43 | # colorSet [ --setaf | --setab | --misc ] var 44 | # Assigns the selected set of escape mappings to the given associative array names. 45 | function colorSet { 46 | typeset -a clrs msc 47 | typeset x 48 | clrs=(black red green orange blue magenta cyan grey darkgrey ltred ltgreen yellow ltblue ltmagenta ltcyan white) 49 | msc=(sgr0 bold dim smul blink rev invis) 50 | 51 | while ! ${2:+false}; do 52 | ${KSH_VERSION:+eval typeset -n "$2"=\$2} 53 | case ${1#--} in 54 | setaf|setab) 55 | for x in "${!clrs[@]}"; do 56 | eval "$2"'[${clrs[x]}]=$(tput "${1#--}" "$x")' 57 | done 58 | ;; 59 | misc) 60 | for x in "${msc[@]}"; do 61 | eval "$2"'[$x]=$(tput "$x")' 62 | done 63 | ;; 64 | *) 65 | return 1 66 | esac 67 | shift 2 68 | done 69 | } 70 | 71 | # Example code 72 | function main { 73 | typeset -A fgColors bgColors miscEscapes 74 | if colorSet --setaf fgColors --setab bgColors --misc miscEscapes; then 75 | if ! ${1:+${fgColors[$1]:+false}}; then 76 | printf '%s%s%s\n' "${fgColors[$1]}" "this text is ${1}" "${miscEscapes[sgr0]}" >&3 77 | else 78 | printf '%s, %s\n' "${1:-Empty}" 'no such color.' 79 | typeset x y 80 | for x in fgColors bgColors miscEscapes; do 81 | typeset -a keys 82 | eval 'keys=("${!'"$x"'[@]}")' 83 | printf '%s=( ' "$x" 84 | for y in "${keys[@]}"; do 85 | eval 'printf "[%q]=%q " "$y" "${'"$x"'[$y]}"' 86 | done 87 | printf ')\n' 88 | done 89 | return 1 90 | fi 91 | else 92 | echo 'Failed setting color arrays.' 93 | return 1 94 | fi 3>&1 >&2 95 | } 96 | 97 | main "$@" 98 | 99 | # vim: set fenc=utf-8 ff=unix ft=sh : 100 | -------------------------------------------------------------------------------- /docs/howto/collapsing_functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - bash 4 | - shell 5 | - scripting 6 | - example 7 | - function 8 | - collapse 9 | --- 10 | 11 | # Collapsing Functions 12 | 13 | ## What is a "Collapsing Function"? 14 | 15 | A collapsing function is a function whose behavior changes depending 16 | upon the circumstances under which it's run. Function collapsing is 17 | useful when you find yourself repeatedly checking a variable whose value 18 | never changes. 19 | 20 | ## How do I make a function collapse? 21 | 22 | Function collapsing requires some static feature in the environment. A 23 | common example is a script that gives the user the option of having 24 | "verbose" output. 25 | 26 | #!/bin/bash 27 | 28 | [[ $1 = -v || $1 = --verbose ]] && verbose=1 29 | 30 | chatter() { 31 | if [[ $verbose ]]; then 32 | chatter() { 33 | echo "$@" 34 | } 35 | chatter "$@" 36 | else 37 | chatter() { 38 | : 39 | } 40 | fi 41 | } 42 | 43 | echo "Waiting for 10 seconds." 44 | for i in {1..10}; do 45 | chatter "$i" 46 | sleep 1 47 | done 48 | 49 | ## How does it work? 50 | 51 | The first time you run chatter(), the function redefines itself based on 52 | the value of verbose. Thereafter, chatter doesn't check `$verbose`, it 53 | simply is. Further calls to the function reflect its collapsed nature. 54 | If verbose is unset, chatter will echo nothing, with no extra effort 55 | from the developer. 56 | 57 | ## More examples 58 | 59 | !!! warning "FIXME" 60 | Add more examples! 61 | 62 | ```bash 63 | # Somewhat more portable find -executable 64 | # FIXME/UNTESTED (I don't have access to all of the different versions of find.) 65 | # Usage: find PATH ARGS -- use find like normal, except use -executable instead of 66 | # various versions of -perm /+ blah blah and hacks 67 | find() { 68 | hash find || { echo 'find not found!'; exit 1; } 69 | # We can be pretty sure "$0" should be executable. 70 | if [[ $(command find "$0" -executable 2> /dev/null) ]]; then 71 | unset -f find # We can just use the command find 72 | elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then 73 | find() { 74 | typeset arg args 75 | for arg do 76 | [[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg") 77 | done 78 | command find "${args[@]}" 79 | } 80 | elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then 81 | find() { 82 | typeset arg args 83 | for arg do 84 | [[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg") 85 | done 86 | command find "${args[@]}" 87 | } 88 | else # Last resort 89 | find() { 90 | typeset arg args 91 | for arg do 92 | [[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg") 93 | done 94 | command find "${args[@]}" 95 | } 96 | fi 97 | find "$@" 98 | } 99 | ``` 100 | 101 | ```bash 102 | #!/bin/bash 103 | # Using collapsing functions to turn debug messages on/off 104 | 105 | [ "--debug" = "$1" ] && dbg=echo || dbg=: 106 | 107 | 108 | # From now on if you use $dbg instead of echo, you can select if messages will be shown 109 | 110 | $dbg "This message will only be displayed if --debug is specified at the command line 111 | ``` 112 | -------------------------------------------------------------------------------- /docs/syntax/expansion/tilde.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - bash 4 | - shell 5 | - scripting 6 | - expansion 7 | - substitution 8 | - tilde 9 | - home 10 | - homedir 11 | - shortcut 12 | --- 13 | 14 | # Tilde expansion 15 | 16 | ~ 17 | ~/... 18 | 19 | ~NAME 20 | ~NAME/... 21 | 22 | ~+ 23 | ~+/... 24 | 25 | ~- 26 | ~-/... 27 | 28 | The tilde expansion is used to expand to several specific pathnames: 29 | 30 | - home directories 31 | - current working directory 32 | - previous working directory 33 | 34 | Tilde expansion is only performed, when the tilde-construct is at the 35 | beginning of a word, or a separate word. 36 | 37 | If there's nothing to expand, i.e., in case of a wrong username or any 38 | other error condition, the tilde construct is not replaced, it stays 39 | what it is. 40 | 41 | Tilde expansion is also performed everytime a variable is assigned: 42 | 43 | - after the **first** `=`: `TARGET=~moonman/share` 44 | - after **every** `:` (colon) in the assigned value: 45 | `TARGET=file:~moonman/share` 46 | 47 | !!! info "Note" 48 | As of now (Bash 4.3-alpha) the following constructs 49 | **also** works, though it's not a variable assignment: 50 | 51 | echo foo=~ 52 | echo foo=:~ 53 | 54 | I don't know yet, if this is a bug or intended. 55 | 56 | This way you can correctly use the tilde expansion in your 57 | [PATH](../../syntax/shellvars.md#PATH): 58 | 59 | PATH=~/mybins:~peter/mybins:$PATH 60 | 61 | **Spaces in the referenced pathes?** A construct like... 62 | 63 | ~/"my directory" 64 | 65 | ...is perfectly valid and works! 66 | 67 | ## Home directory 68 | 69 | ~ 70 | ~ 71 | 72 | This form expands to the home-directory of the current user (`~`) or the 73 | home directory of the given user (`~`). 74 | 75 | If the given user doesn't exist (or if his home directory isn't 76 | determinable, for some reason), it doesn't expand to something else, it 77 | stays what it is. The requested home directory is found by asking the 78 | operating system for the associated home directory for ``. 79 | 80 | To find the home directory of the current user (`~`), Bash has a 81 | precedence: 82 | 83 | - expand to the value of [HOME](../../syntax/shellvars.md#HOME) if it's 84 | defined 85 | - expand to the home directory of the user executing the shell 86 | (operating system) 87 | 88 | That means, the variable `HOME` can override the "real" home 89 | directory, at least regarding tilde expansion. 90 | 91 | ## Current working directory 92 | 93 | ~+ 94 | 95 | This expands to the value of the [PWD](../../syntax/shellvars.md#PWD) variable, 96 | which holds the currect working directory: 97 | 98 | echo "CWD is $PWD" 99 | 100 | is equivalent to (note it **must** be a separate word!): 101 | 102 | echo "CWD is" ~+ 103 | 104 | ## Previous working directory 105 | 106 | ~- 107 | 108 | This expands to the value of the [OLDPWD](../../syntax/shellvars.md#OLDPWD) 109 | variable, which holds the previous working directory (the one before the 110 | last `cd`). If `OLDPWD` is unset (never changed the directory), it is 111 | not expanded. 112 | 113 | $ pwd 114 | /home/bash 115 | $ cd /etc 116 | $ echo ~- 117 | /home/bash 118 | 119 | ## See also 120 | 121 | - Internal: [Introduction to expansion and 122 | substitution](../../syntax/expansion/intro.md) 123 | -------------------------------------------------------------------------------- /docs/misc/bashphorisms.md: -------------------------------------------------------------------------------- 1 | # The Bashphorisms 2 | 3 | Bashphorisms are aphorisms for the IRC channel `#bash` on Freenode. Keep 4 | in mind that this version is a snapshot, the bashphorisms are changed 5 | here and there. Also, [another 6 | snapshot](http://mywiki.wooledge.org/BashFAQ/064). 7 | 8 | I think `greycat` was the first one who had the idea, but I'm not sure. 9 | 10 | Our bashphorisms can be queried from `greybot` using `!bN`, where `N` is 11 | the bashphorism number. 12 | 13 | And yes, these bashphorisms reflect the daily reality in `#bash`. 14 | 15 | |Number|Bashphorism| 16 | |------|-----------| 17 | |0|The questioner will never tell you what they are really doing the first time they ask.| 18 | |1|The questioner's first description of the problem/question will be misleading.| 19 | |2|The questioner will keep changing the question until it drives the helpers in the channel insane.| 20 | |3|Offtopicness will continue until someone asks a bash question that falls under bashphorisms 1 and/or 2, and `greycat` gets pissed off.| 21 | |4|The questioner will not read and apply the answers he is given but will instead continue to practice bashphorism #1 and bashphorism #2.| 22 | |5|The ignorant will continually mis-educate the other noobies.| 23 | |6|When given a choice of solutions, the newbie will always choose the wrong one.| 24 | |7|The newbie will always find a reason to say, "It doesn't work."| 25 | |8|If you don't know to whom the bashphorism's referring, it's you.| 26 | |9|All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question.| 27 | |10|See B1| 28 | |11|Please apply `(( % 10 ))` to the bashphorism value.| 29 | |12|All logic is deniable; however, some logic will *plonk* you if you deny it.| 30 | |13|Everyone ignores greycat when he is right. When he is wrong, it is !b1| 31 | |14|The newbie doesn't actually know what he's asking. If he did, he wouldn't need to ask.| 32 | |15|The more advanced you are, the more likely you are to be overcomplicating it.| 33 | |16|The more beginner you are, the more likely you are to be overcomplicating it.| 34 | |17|A newbie comes to #bash to get his script confirmed. He leaves disappointed.| 35 | |18|The newbie will not accept the answer you give, no matter how right it is.| 36 | |19|The newbie is a bloody loon.| 37 | |20|The newbie will always have some excuse for doing it wrong.| 38 | |21|When the newbie's question is ambiguous, the proper interpretation will be whichever one makes the problem the hardest to solve.| 39 | |22|The newcomer will abuse the bot's factoid triggers for their own entertainment until someone gets annoyed enough to ask them to message it privately instead.| 40 | |23|Everyone is a newcomer.| 41 | |24|The newcomer will address greybot as if it were human.| 42 | |25|The newbie won't accept any answer that uses practical or standard tools.| 43 | |26|The newbie will not TELL you about this restriction until you have wasted half an hour.| 44 | |27|The newbie will lie.| 45 | |28|When the full horror of the newbie's true goal is revealed, the newbie will try to restate the goal to trick you into answering. Newbies are stupid.| 46 | |29|It's always git. Or python virtualenv. Or docker. One of those pieces of shit. ALWAYS.| 47 | |30|They won't show you the homework assignment. That would make it too easy.| 48 | |31|Your teacher is a f**king idiot.| 49 | |32|The more horrifyingly wrong a proposed solution is, the more likely it will be used.| 50 | |33|The newbie cannot explain what he is doing, or why. He will show you incomprehensible, nonworking code instead. What? You can't read his mind?!| 51 | 52 | Please feel free to correct or extend this page whenever needed. 53 | -------------------------------------------------------------------------------- /original_source/syntax/expansion/intro.txt: -------------------------------------------------------------------------------- 1 | ====== Expansions and substitutions ====== 2 | 3 | {{keywords>bash shell scripting expansion substitution text variable filename macro wildcard}} 4 | 5 | Before executing your commands, Bash checks whether there are any syntax elements in the command line that should be interpreted rather than taken literally. After splitting the command line into tokens (words), Bash scans for these special elements and interprets them, resulting in a changed command line: the elements are said to be **expanded** to or **substituted** to **new text and maybe new tokens** (words). 6 | 7 | The most simple example of this behaviour is a referenced variable: 8 | 9 | mystring="Hello world" 10 | echo "$mystring" 11 | 12 | The ''echo'' program definitely doesn't care about what a shell variable is. It is Bash's job to deal with the variable. Bash **expands** the string "''$mystring''" to "''Hello world''", so that ''echo'' will only see ''Hello world'', not the variable or anything else! 13 | 14 | After all these expansions and substitutions are done, all quotes that are not meant literally (i.e., [[syntax:quoting | the quotes that marked contiguous words]], as part of the shell syntax) are removed from the commandline text, so the called program won't see them. This step is called **quote-removal**. 15 | 16 | ===== Overview ===== 17 | 18 | Saw a possible expansion syntax but don't know what it is? Here's a small list. 19 | 20 | * [[syntax:pe | Parameter expansion]] (it has its own [[syntax:pe#overview | overview section]]) 21 | * ''$WORD'' 22 | * ''${STUFF...}'' 23 | * [[syntax:expansion:globs | Pathname expansion]] 24 | * ''*.txt'' 25 | * ''page_1?.html'' 26 | * [[syntax:expansion:arith | Arithmetic expansion]] 27 | * ''$(( EXPRESSION ))'' 28 | * ''$[ EXPRESSION ]'' 29 | * [[syntax:expansion:cmdsubst | Command substitution]] 30 | * ''$( COMMAND )'' 31 | * ''` COMMAND `'' 32 | * [[syntax:expansion:tilde | Tilde expansion]] 33 | * ''~'' 34 | * ''~+'' 35 | * ''~-'' 36 | * [[syntax:expansion:brace | Brace expansion]] 37 | * ''{X,Y,Z}'' 38 | * ''{X..Y}'' 39 | * ''{X..Y..Z}'' 40 | * [[syntax:expansion:proc_subst | Process substitution]] 41 | * ''<( COMMAND )'' 42 | * ''>( COMMAND )'' 43 | 44 | ===== Order ===== 45 | Bash performs expansions and substitutions in a defined order. This explains why globbing (pathname expansion), for example, is safe to use on filenames with spaces (because it happens **after** the final word splitting!). 46 | 47 | The order is (from first to last): 48 | 49 | * [[syntax:expansion:brace | Brace expansion]] 50 | * [[syntax:expansion:tilde | Tilde expansion]] 51 | * The following expansions happen at the same time, in a left-to-right fashion on the commandline (see below) 52 | * [[syntax:pe | Parameter expansion]] 53 | * [[syntax:expansion:arith | Arithmetic expansion]] 54 | * [[syntax:expansion:cmdsubst | Command substitution]] 55 | * [[syntax:expansion:wordsplit | Word splitting]] 56 | * [[syntax:expansion:globs | Pathname expansion]] 57 | 58 | [[syntax:expansion:proc_subst | Process substitution]] is performed **simultaneously** with [[syntax:pe | parameter expansion]], [[syntax:expansion:cmdsubst | command substitution]] and [[syntax:expansion:arith | arithmetic expansion]]. It is only performed when the underlying operating system supports it. 59 | 60 | The 3 steps [[syntax:pe | parameter expansion]], [[syntax:expansion:arith | arithmetic expansion]] and [[syntax:expansion:cmdsubst | command substitution]] happen at the same time in a left-to-right fashion on nthe commandline. This means 61 | 62 | i=1 63 | echo $i $((i++)) $i 64 | 65 | will output ''1 1 2'' and not ''1 1 1''. 66 | -------------------------------------------------------------------------------- /docs/snipplets/add_color_to_your_scripts.md: -------------------------------------------------------------------------------- 1 | # Add Color to your scripts 2 | 3 | ---- dataentry snipplet ---- snipplet_tags : terminal, color 4 | LastUpdate_dt : 2013-03-23 Contributors : Frank Lazzarini, Dan Douglas 5 | type : snipplet 6 | 7 | ------------------------------------------------------------------------ 8 | 9 | Make your scripts output more readable using bash colors. Simply add 10 | these variables to your script, and you will be able to echo in color. 11 | (I haven't added all the colors available, just some basics) 12 | 13 | # Colors 14 | ESC_SEQ="\x1b[" 15 | COL_RESET=$ESC_SEQ"39;49;00m" 16 | COL_RED=$ESC_SEQ"31;01m" 17 | COL_GREEN=$ESC_SEQ"32;01m" 18 | COL_YELLOW=$ESC_SEQ"33;01m" 19 | COL_BLUE=$ESC_SEQ"34;01m" 20 | COL_MAGENTA=$ESC_SEQ"35;01m" 21 | COL_CYAN=$ESC_SEQ"36;01m" 22 | 23 | Now if you want to output some text in color use *echo -e* instead of 24 | just echo. And always remember to use the *\$COL_RESET* variable to 25 | reset the color changes in bash. Like so \.... 26 | 27 | echo -e "$COL_RED This is red $COL_RESET" 28 | echo -e "$COL_BLUE This is blue $COL_RESET" 29 | echo -e "$COL_YELLOW This is yellow $COL_RESET" 30 | 31 | But also see the notes in [the article about using 32 | terminalcodes](../scripting/terminalcodes.md) about generating codes and 33 | hardwiring codes. 34 | 35 | This snipplet sets up associative arrays for basic color codes using 36 | `tput` for Bash, ksh93 or zsh. You can pass it variable names to 37 | correspond with a collection of codes. There's a `main` function with 38 | example usage. 39 | 40 | ``` bash 41 | #!/usr/bin/env bash 42 | 43 | ${ZSH_VERSION+false} || emulate ksh 44 | ${BASH_VERSION+shopt -s lastpipe extglob} 45 | 46 | # colorSet [ --setaf | --setab | --misc ] var 47 | # Assigns the selected set of escape mappings to the given associative array names. 48 | function colorSet { 49 | typeset -a clrs msc 50 | typeset x 51 | clrs=(black red green orange blue magenta cyan grey darkgrey ltred ltgreen yellow ltblue ltmagenta ltcyan white) 52 | msc=(sgr0 bold dim smul blink rev invis) 53 | 54 | while ! ${2:+false}; do 55 | ${KSH_VERSION:+eval typeset -n "$2"=\$2} 56 | case ${1#--} in 57 | setaf|setab) 58 | for x in "${!clrs[@]}"; do 59 | eval "$2"'[${clrs[x]}]=$(tput "${1#--}" "$x")' 60 | done 61 | ;; 62 | misc) 63 | for x in "${msc[@]}"; do 64 | eval "$2"'[$x]=$(tput "$x")' 65 | done 66 | ;; 67 | *) 68 | return 1 69 | esac 70 | shift 2 71 | done 72 | } 73 | 74 | # Example code 75 | function main { 76 | typeset -A fgColors bgColors miscEscapes 77 | if colorSet --setaf fgColors --setab bgColors --misc miscEscapes; then 78 | if ! ${1:+${fgColors[$1]:+false}}; then 79 | printf '%s%s%s\n' "${fgColors[$1]}" "this text is ${1}" "${miscEscapes[sgr0]}" >&3 80 | else 81 | printf '%s, %s\n' "${1:-Empty}" 'no such color.' 82 | typeset x y 83 | for x in fgColors bgColors miscEscapes; do 84 | typeset -a keys 85 | eval 'keys=("${!'"$x"'[@]}")' 86 | printf '%s=( ' "$x" 87 | for y in "${keys[@]}"; do 88 | eval 'printf "[%q]=%q " "$y" "${'"$x"'[$y]}"' 89 | done 90 | printf ')\n' 91 | done 92 | return 1 93 | fi 94 | else 95 | echo 'Failed setting color arrays.' 96 | return 1 97 | fi 3>&1 >&2 98 | } 99 | 100 | main "$@" 101 | 102 | # vim: set fenc=utf-8 ff=unix ft=sh : 103 | ``` 104 | -------------------------------------------------------------------------------- /original_source/commands/builtin/echo.txt: -------------------------------------------------------------------------------- 1 | ====== The echo builtin command ====== 2 | 3 | ===== Synopsis ===== 4 | 5 | echo [-neE] [arg ...] 6 | 7 | 8 | ===== Description ===== 9 | ''echo'' outputs it's args to stdout, separated by spaces, followed by a newline. The return status is always ''0''. If the [[commands:builtin:shopt|shopt]] option ''xpg_echo'' is set, Bash dynamically determines whether echo should expand escape characters (listed below) by default based on the current platform. ''echo'' doesn't interpret ''--'' as the end of options, and will simply print this string if given. 10 | 11 | ==== Options ==== 12 | ^Option ^Description ^ 13 | | ''-n'' | The trailing newline is suppressed. | 14 | | ''-e'' | Interpretation of the following backslash-escaped characters (below) is enabled. | 15 | | ''-E'' | Disables the interpretation of these escape characters, even on systems where they are interpreted by default. | 16 | 17 | ==== Escape sequences ==== 18 | ^Escape ^Description ^ 19 | | ''\a'' | alert (bell) | 20 | | ''\b'' | backspace | 21 | | ''\c'' | suppress further output | 22 | | ''\e'' | | 23 | | ''\E'' | an escape character | 24 | | ''\f'' | form feed | 25 | | ''\n'' | new line | 26 | | ''\r'' | carriage return | 27 | | ''\t'' | horizontal tab | 28 | | ''\v'' | vertical tab | 29 | | ''\\'' | backslash | 30 | | ''\0nnn'' | the eight-bit character whose value is the octal value nnn (zero to three octal digits) | 31 | | ''\xHH'' | the eight-bit character whose value is the hexadecimal value HH (one or two hex digits) | 32 | | ''\uHHHH'' | the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits) | 33 | | ''\UHHHHHHHH'' | the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits) | 34 | 35 | ===== Examples ===== 36 | 37 | 38 | ===== Portability considerations ===== 39 | * ''echo'' is a portability train wreck. No major shell follows POSIX completely, and any shell that attempts to do so should be considered horribly broken. [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37|SUSv4]] specifies that ''echo'' **shall not** include any options. Further, it specifies that the behavior of ''-n'' as a first argument shall be determined by the implementation, unless XSI is followed, in which case ''-n'' is always treated as a string, and backslash escapes are interpreted by default. ''dash'' has the misfeature of following this and interpreting escapes by default, but includes a ''-n'' feature for suppressing newlines nevertheless.\\ \\ In practice, if you're able to assume a korn-like shell including bash, mksh, or zsh, ''echo'' when used in simple cases is generally reliable. For example, in the very common situation in which echo is supplied with a single argument and whose output is to have a newline appended, using ''echo'' is considered common practice. 40 | 41 | * **Never use options to ''echo''! //Ever//!** Any time you feel tempted to use ''echo -e'', ''-n'', or any other special feature of echo, **use [[commands:builtin:printf|printf]] instead!** If portability is a requirement, you should consider using ''printf'' //exclusively// and just ignore that ''echo'' even exists. If you must use ''echo -e'' and refuse to use ''printf'', it is usually acceptable to use ''echo $'...' ''if targeting only shells that support this special quoting style. 42 | 43 | * ''ksh93'' has a ''print'' command, which if coding specifically for ''ksh93'' should be preferred over ''echo''. [[commands:builtin:printf|printf]] still includes most of the functionality of both, and should usually be the most preferred option. 44 | 45 | ===== See also ===== 46 | * [[commands:builtin:printf]] 47 | * http://cfajohnson.com/shell/cus-faq.html#Q0b 48 | * http://www.in-ulm.de/~mascheck/various/echo+printf/ -------------------------------------------------------------------------------- /docs/commands/builtin/echo.md: -------------------------------------------------------------------------------- 1 | # The echo builtin command 2 | 3 | ## Synopsis 4 | 5 | echo [-neE] [arg ...] 6 | 7 | ## Description 8 | 9 | `echo` outputs it's args to stdout, separated by spaces, followed by a 10 | newline. The return status is always `0`. If the 11 | [shopt](../../commands/builtin/shopt.md) option `xpg_echo` is set, Bash 12 | dynamically determines whether echo should expand escape characters 13 | (listed below) by default based on the current platform. `echo` doesn't 14 | interpret `--` as the end of options, and will simply print this string 15 | if given. 16 | 17 | ### Options 18 | 19 | Option|Description| 20 | ------|-----------| 21 | |`-n`|The trailing newline is suppressed.| 22 | |`-e`|Interpretation of the following backslash-escaped characters (below) is enabled.| 23 | |`-E`|Disables the interpretation of these escape characters, even on systems where they are interpreted by default.| 24 | 25 | ### Escape sequences 26 | 27 | |Escape|Description| 28 | |------|-----------| 29 | |`\a`|alert (bell)| 30 | |`\b`|backspace| 31 | |`\c`|suppress further output| 32 | |`\e`| 33 | |`\E`|an escape character| 34 | |`\f`|form feed| 35 | |`\n`|new line| 36 | |`\r`|carriage return| 37 | |`\t`|horizontal tab| 38 | |`\v`|vertical tab| 39 | |`\\`|backslash| 40 | |`\0nnn`|the eight-bit character whose value is the octal value nnn (zero to three octal digits)| 41 | |`\xHH`|the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)| 42 | |`\uHHHH`|the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)| 43 | |`\UHHHHHHHH`|the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)| 44 | 45 | ## Examples 46 | 47 | ## Portability considerations 48 | 49 | - `echo` is a portability train wreck. No major shell follows POSIX 50 | completely, and any shell that attempts to do so should be 51 | considered horribly broken. 52 | [SUSv4](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37) 53 | specifies that `echo` **shall not** include any options. Further, it 54 | specifies that the behavior of `-n` as a first argument shall be 55 | determined by the implementation, unless XSI is followed, in which 56 | case `-n` is always treated as a string, and backslash escapes are 57 | interpreted by default. `dash` has the misfeature of following this 58 | and interpreting escapes by default, but includes a `-n` feature for 59 | suppressing newlines nevertheless. 60 | 61 | In practice, if you're able to assume a korn-like shell including 62 | bash, mksh, or zsh, `echo` when used in simple cases is generally 63 | reliable. For example, in the very common situation in which echo is 64 | supplied with a single argument and whose output is to have a 65 | newline appended, using `echo` is considered common practice. 66 | 67 | - **Never use options to `echo`! *Ever*!** Any time you feel tempted 68 | to use `echo -e`, `-n`, or any other special feature of echo, **use 69 | [printf](../../commands/builtin/printf.md) instead!** If portability is a 70 | requirement, you should consider using `printf` *exclusively* and 71 | just ignore that `echo` even exists. If you must use `echo -e` and 72 | refuse to use `printf`, it is usually acceptable to use \'\'echo 73 | \$\'\...\' \'\'if targeting only shells that support this special 74 | quoting style. 75 | 76 | - `ksh93` has a `print` command, which if coding specifically for 77 | `ksh93` should be preferred over `echo`. 78 | [printf](../../commands/builtin/printf.md) still includes most of the 79 | functionality of both, and should usually be the most preferred 80 | option. 81 | 82 | ## See also 83 | 84 | - [printf](../../commands/builtin/printf.md) 85 | - 86 | - 87 | -------------------------------------------------------------------------------- /docs/syntax/expansion/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | tags: 3 | - bash 4 | - shell 5 | - scripting 6 | - expansion 7 | - substitution 8 | - text 9 | - variable 10 | - filename 11 | - macro 12 | - wildcard 13 | --- 14 | 15 | # Expansions and substitutions 16 | 17 | Before executing your commands, Bash checks whether there are any syntax 18 | elements in the command line that should be interpreted rather than 19 | taken literally. After splitting the command line into tokens (words), 20 | Bash scans for these special elements and interprets them, resulting in 21 | a changed command line: the elements are said to be **expanded** to or 22 | **substituted** to **new text and maybe new tokens** (words). 23 | 24 | The most simple example of this behaviour is a referenced variable: 25 | 26 | mystring="Hello world" 27 | echo "$mystring" 28 | 29 | The `echo` program definitely doesn't care about what a shell variable 30 | is. It is Bash's job to deal with the variable. Bash **expands** the 31 | string "`$mystring`" to "`Hello world`", so that `echo` will only 32 | see `Hello world`, not the variable or anything else! 33 | 34 | After all these expansions and substitutions are done, all quotes that 35 | are not meant literally (i.e., [the quotes that marked contiguous 36 | words](../../syntax/quoting.md), as part of the shell syntax) are removed from 37 | the commandline text, so the called program won't see them. This step 38 | is called **quote-removal**. 39 | 40 | ## Overview 41 | 42 | Saw a possible expansion syntax but don't know what it is? Here's a 43 | small list. 44 | 45 | - [Parameter expansion](../../syntax/pe.md) (it has its own [overview 46 | section](../../syntax/pe.md#overview)) 47 | - `$WORD` 48 | - `${STUFF...}` 49 | - [Pathname expansion](../../syntax/expansion/globs.md) 50 | - `*.txt` 51 | - `page_1?.html` 52 | - [Arithmetic expansion](../../syntax/expansion/arith.md) 53 | - `$(( EXPRESSION ))` 54 | - `$[ EXPRESSION ]` 55 | - [Command substitution](../../syntax/expansion/cmdsubst.md) 56 | - `$( COMMAND )` 57 | - `` ` COMMAND ` `` 58 | - [Tilde expansion](../../syntax/expansion/tilde.md) 59 | - `~` 60 | - `~+` 61 | - `~-` 62 | - [Brace expansion](../../syntax/expansion/brace.md) 63 | - `{X,Y,Z}` 64 | - `{X..Y}` 65 | - `{X..Y..Z}` 66 | - [Process substitution](../../syntax/expansion/proc_subst.md) 67 | - `<( COMMAND )` 68 | - `>( COMMAND )` 69 | 70 | ## Order 71 | 72 | Bash performs expansions and substitutions in a defined order. This 73 | explains why globbing (pathname expansion), for example, is safe to use 74 | on filenames with spaces (because it happens **after** the final word 75 | splitting!). 76 | 77 | The order is (from first to last): 78 | 79 | - [Brace expansion](../../syntax/expansion/brace.md) 80 | - [Tilde expansion](../../syntax/expansion/tilde.md) 81 | - The following expansions happen at the same time, in a left-to-right 82 | fashion on the commandline (see below) 83 | - [Parameter expansion](../../syntax/pe.md) 84 | - [Arithmetic expansion](../../syntax/expansion/arith.md) 85 | - [Command substitution](../../syntax/expansion/cmdsubst.md) 86 | - [Word splitting](../../syntax/expansion/wordsplit.md) 87 | - [Pathname expansion](../../syntax/expansion/globs.md) 88 | 89 | [Process substitution](../../syntax/expansion/proc_subst.md) is performed 90 | **simultaneously** with [parameter expansion](../../syntax/pe.md), [command 91 | substitution](../../syntax/expansion/cmdsubst.md) and [arithmetic 92 | expansion](../../syntax/expansion/arith.md). It is only performed when the 93 | underlying operating system supports it. 94 | 95 | The 3 steps [parameter expansion](../../syntax/pe.md), [arithmetic 96 | expansion](../../syntax/expansion/arith.md) and [command 97 | substitution](../../syntax/expansion/cmdsubst.md) happen at the same time in a 98 | left-to-right fashion on nthe commandline. This means 99 | 100 | i=1 101 | echo $i $((i++)) $i 102 | 103 | will output `1 1 2` and not `1 1 1`. 104 | --------------------------------------------------------------------------------