Added introduction.
This commit is contained in:
@@ -1,50 +1,188 @@
|
||||
# File Paths
|
||||
# File handling
|
||||
|
||||
## Get the directory name of a file path
|
||||
**CAVEAT:** `bash` doesn't handle binary data properly in versions `< 4.4`.
|
||||
|
||||
Alternative to the `dirname` command.
|
||||
## Read a file to a string
|
||||
|
||||
Alternative to the `cat` command.
|
||||
|
||||
```shell
|
||||
file_data="$(<"file")"
|
||||
```
|
||||
|
||||
## Read a file to an array (*by line*)
|
||||
|
||||
Alternative to the `cat` command.
|
||||
|
||||
```shell
|
||||
# Bash <4
|
||||
IFS=$'\n' read -d "" -ra file_data < "file"
|
||||
|
||||
# Bash 4+
|
||||
mapfile -t file_data < "file"
|
||||
```
|
||||
|
||||
## Get the first N lines of a file
|
||||
|
||||
Alternative to the `head` command.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
dirname() {
|
||||
# Usage: dirname "path"
|
||||
printf '%s\n' "${1%/*}/"
|
||||
head() {
|
||||
# Usage: head "n" "file"
|
||||
mapfile -tn "$1" line < "$2"
|
||||
printf '%s\n' "${line[@]}"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ dirname ~/Pictures/Wallpapers/1.jpg
|
||||
/home/black/Pictures/Wallpapers/
|
||||
$ head 2 ~/.bashrc
|
||||
# Prompt
|
||||
PS1='➜ '
|
||||
|
||||
$ dirname ~/Pictures/Downloads/
|
||||
/home/black/Pictures/
|
||||
$ head 1 ~/.bashrc
|
||||
# Prompt
|
||||
```
|
||||
|
||||
## Get the base-name of a file path
|
||||
## Get the last N lines of a file
|
||||
|
||||
Alternative to the `basename` command.
|
||||
Alternative to the `tail` command.
|
||||
|
||||
**CAVEAT:** Requires `bash` 4+
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
basename() {
|
||||
# Usage: basename "path"
|
||||
: "${1%/}"
|
||||
printf '%s\n' "${_##*/}"
|
||||
tail() {
|
||||
# Usage: tail "n" "file"
|
||||
mapfile -tn 0 line < "$2"
|
||||
printf '%s\n' "${line[@]: -$1}"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ basename ~/Pictures/Wallpapers/1.jpg
|
||||
1.jpg
|
||||
$ tail 2 ~/.bashrc
|
||||
# Enable tmux.
|
||||
# [[ -z "$TMUX" ]] && exec tmux
|
||||
|
||||
$ basename ~/Pictures/Downloads/
|
||||
Downloads
|
||||
$ tail 1 ~/.bashrc
|
||||
# [[ -z "$TMUX" ]] && exec tmux
|
||||
```
|
||||
|
||||
## Get the number of lines in a file
|
||||
|
||||
Alternative to `wc -l`.
|
||||
|
||||
**Example Function (bash 4):**
|
||||
|
||||
```sh
|
||||
lines() {
|
||||
# Usage: lines "file"
|
||||
mapfile -tn 0 lines < "$1"
|
||||
printf '%s\n' "${#lines[@]}"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Function (bash 3):**
|
||||
|
||||
This method uses less memory than the `mapfile` method and it's more
|
||||
compatible but it's slower for bigger files.
|
||||
|
||||
```sh
|
||||
lines_loop() {
|
||||
# Usage: lines_loop "file"
|
||||
count=0
|
||||
while IFS= read -r _; do
|
||||
((count++))
|
||||
done < "$1"
|
||||
printf '%s\n' "$count"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
$ lines ~/.bashrc
|
||||
48
|
||||
|
||||
$ lines_loop ~/.bashrc
|
||||
48
|
||||
```
|
||||
|
||||
## Count files or directories in directory
|
||||
|
||||
This works by passing the output of the glob as function arguments. We
|
||||
then count the arguments and print the number.
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
count() {
|
||||
# Usage: count /path/to/dir/*
|
||||
# count /path/to/dir/*/
|
||||
printf '%s\n' "$#"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
# Count all files in dir.
|
||||
$ count ~/Downloads/*
|
||||
232
|
||||
|
||||
# Count all dirs in dir.
|
||||
$ count ~/Downloads/*/
|
||||
45
|
||||
|
||||
# Count all jpg files in dir.
|
||||
$ count ~/Pictures/*.jpg
|
||||
64
|
||||
```
|
||||
|
||||
## Create an empty file
|
||||
|
||||
Alternative to `touch`.
|
||||
|
||||
```shell
|
||||
# Shortest.
|
||||
:> file
|
||||
|
||||
# Longer alternatives:
|
||||
echo -n > file
|
||||
printf '' > file
|
||||
```
|
||||
|
||||
## Extract lines between two markers
|
||||
|
||||
**Example Function:**
|
||||
|
||||
```sh
|
||||
extract() {
|
||||
# Usage: extract file "opening marker" "closing marker"
|
||||
while IFS=$'\n' read -r line; do
|
||||
[[ "$extract" && "$line" != "$3" ]] && \
|
||||
printf '%s\n' "$line"
|
||||
|
||||
[[ "$line" == "$2" ]] && extract=1
|
||||
[[ "$line" == "$3" ]] && extract=
|
||||
done < "$1"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```shell
|
||||
# Extract code blocks from MarkDown file.
|
||||
$ extract ~/projects/pure-bash/README.md '```sh' '```'
|
||||
# Output here...
|
||||
```
|
||||
|
||||
<!-- CHAPTER END -->
|
||||
|
||||
Reference in New Issue
Block a user