[指令] Command Line 操作
keywords: zsh
, iterm2
, terminal
, linux
, unix
open -a [appToOpen] [fileName] # 指定特定應用程式開啟檔案
tail -f [filename] # 從結尾開始讀檔,並且持續監控變化
history | grep [pattern] # 找出最近在 terminal 中輸入的內容
Linux Terminal Command Reference @ linux community
變數
$PATH
所有能夠在 Terminal 中直接被執行的程式,都需要放在 $PATH
內,否則需要先指定到該程式所在的資料夾後才能執行。
echo $PATH
如果想要將其他路徑添加到 $PATH
中,可以在 .bash_profile
或 .zshrc
中使用:
- 在
PATH=""
後面使用$PATH
是為了把原本已有的PATH
保留下來,否則會覆蓋掉。 - 用
:
當作不同路徑的區隔
# .zshrc
export PATH="$PATH:~/my-scrips"
$SHELL / $0
當前 Terminal 使用的 shell:
echo $SHELL # /opt/homebrew/bin/zsh
echo $0 # -zsh
$USER / $USERNAME
使用者名稱:
echo $USER # pjchender
echo $USERNAME # pjchender
操作資料夾
cd <directory> # 切換目錄
pwd # 取得目前所在的位置
ls -alpt # 列出目前的檔案列表,搭配 -a(顯示隱藏檔), -l(顯示完整資訊),
# -p(顯示較清楚),-t(根據最後修改時間排序檔案)
ls | wc -l # 顯示檔案數量
mkdir <directory> # 建立新的目錄
mkdir -p ~/Library/a_folder # 即使 Library 資料夾不存在也直接建立到 a_folder
touch # 建立檔案
cp <file> <directory> # 複製檔案
cp index.html about.html # 把檔案 index.html 複製一份成 about.html
cp -r a_folder b_bolder # 把 a_folder 資料夾複製進去 b_folder 資料夾中
mv <file-old> <file-new|directory> # 移動檔案
mv index.html info.html # 把檔案 index.html 更名成 info.html(重新命名、改名)
mv index.html a_folder/ # 把 index.html 移動到 a_folder 資料夾中
rm <file|directory> # 刪除檔案
rm *.html # 刪除目錄中的所有 html
rm -r <folder> # 刪除整個 a_folder
rm -f <file> # 刪除檔案
rm -rf [folder_name] # 刪除資料夾(不論裡面有沒有內容或其他資料夾)
sudo # 暫時取得權限
改變資料與檔案權限 chmod
$ chmod 644 * # 檔案用 644
$ chmod 755 * # 目錄用 755
# 一次修改因為檔案權限修改後,使得 git 認為檔案不同的情況
$ git ls-files -m | xargs chmod 644
# 一次修改所有資料夾底下的檔案或檔案
$ find YOUR_PATH -type d | xargs chmod 755
$ find YOUR_PATH -type f | xargs chmod 644
$ sudo find /path/to/dir -type f -exec chmod 0664 {} \; # 如果上一行出現錯誤,可試試這行
補充:
# 文件的權限類型
rwx = 111 = 7
rw- = 110 = 6
r-x = 101 = 5
r-- = 100 = 4
-wx = 011 = 3
-w- = 010 = 2
--x = 001 = 1
--- = 000 = 0
# 文件所屬群組
<擁有者> - <群組> - <其它>
讀取檔案
cat <file> # 將檔案內容輸出在終端機上
less <file> # 使用分頁的方式顯示內容
head <file> # 只顯示檔案的前 10 行
man open # 查看 open 指令說明
open # 開啟檔案
open -a [appToOpen] [fileName] # 指定特定應用程式開啟檔案
寫入檔案
# <cmd> > <file> # 將 <cmd> 的內容寫入 <file>
echo "my content" > my_file.rb # 取代原本的檔案內容
# <cmd> >> <file> # 將 <cmd> 的內容添加到 <file>
echo "my content" >> my_file.rb # 添加到原本的檔案內容
找檔案
# 尋找空檔案
$ find . -empty
# 尋找名稱後綴為 .del 的資料夾
# -iname 表示 case insensitive
# -type 表示要資料夾(directory)或檔案(file)
$ find . -iname '*.del' -type d
# 尋找名稱後綴為 .del 的檔案
$ find . -iname '*.del' -type f
# 尋找名稱副檔名為 .tsx 的檔案,但不要找 node_modules 裡的
$ find . -type f -name '*.tsx' ! -path "./node_modules/*"
grep:找檔案中的內容
$ grep -ir '<content-to-find>' '<folder-path>'
# i: case-insensitive
# r: recursive
# l: 只顯示資料夾
$ grep -irl 'foobar' . # 從當前目錄開始找
搜尋某一檔案中的內容:
# 找出 .env 中以 "#" 開頭資料
$ grep '^#' .env
# 找出 .env 中不是以 "#" 開頭的資料
$ grep -v '^#' .env
剪貼簿(clipboard)
keywords: pbcopy
, pbpaste
# 複製
$ git diff | pbcopy # 將 stdout 的結果複製到剪貼簿
$ pbcopy < tsconfig.json # 將檔案內容複製到剪貼簿
# 貼上
$ pbpaste > foo.json # 將剪貼簿的內容貼到檔案內
glob
如果好奇該 glob 會匹配到的檔案有哪些,可以使用 echo
查看,例如:
echo (styles|constants)/**/dist # 在 styles 或 constants 資料夾內的 dist
echo packages/*
asterisk
What is the ** glob character? @ StackOverflow
使用單一個星號(single asterisk),可以用來匹配一層內的資料夾,例如 /x/*/y
可以匹配到:
/x/a/y
/x/b/y
但如果是使用雙個星號(double asterisk),則會以 recursive 的方式匹配,例如 /x/**/y
可以匹配到:
/x/any/number/of/levels/y
同時,如果不只是資料夾,還要針對特定副檔名時,可以這樣寫:
const path = [
'*.js', // 該層內所有副檔名為 .js 檔案(不管檔名)
'index.*', // 該層內所有檔名為 index 的檔案(不管副檔名)
'packages/*', // packages 下一層內的所有檔案
'packages/*/*.json', // packages/b/package.json
// packages/a/package.json
'packages/**/*.json', // packages/a/node_modules/lodash/package.json
// packages/a/node_modules/the-answer/package.json
// packages/a/package-lock.json
// packages/a/package.json
// packages/b/package.json
'packages/**/*', // packages 內的所有檔案
'src/index.js', // 一定要是 src/index.js
'src/js/*.js', // 匹配到 src/js/ 裡的所有 .js
'src/js/**/*.js', // 匹配到 src/js/any/number/of/level/ 裡的所有 .js
];
cron:設定 cron jobs
參考網站
- crontab guru:將設定轉成語義化的說明
- Cron Jobs: The Complete Guide @ Cronitor
語法
設定格式
* * * * * sh /path/to/script.sh
- - - - -
| | | | |
| | | | +----- day of week(0-6 | Sun-Sat)
| | | +---------- month (1-12)
| | +--------------- day of month (1-31)
| +-------------------- hour (0-23)
+------------------------- minute (0-59)
格式範例
m h d m d
5 2 * * * # 每天的 02:05:00 會執行(At 02:05)
5 * * * * # 每天每小時的 **:05:00 會執行(At minute 5)
# range of value
5 0-2 * * * # 每天的 00:05:00, 01:05:00, 02:05:00 會執行
# value list separator
0 0 1,15 * * # 每個月的 1 號和 5 號的 00:00:00 會執行(At 00:00 on day-of-month 1 and 15.)
# step values
0 */2 * * * # 每兩小時的 **:00:00 會執行
*/15 * * * * # 每 15 分鐘會執行
# combination
0 4-8/2 * * * # 每天 04:00:00~08:00:00 的每兩小時會執行
設定 cron jobs
# 進入設定檔
EDITOR=vim crontab -e
假設我們寫了一個 Shell Script,檔名是 ~/test.sh
:
test.sh
#! /bin/bash
echo "The time is $(date)"
使用 crontab
進入設定檔後,即可寫入:
* * * * * sh /path/to/test.sh
# Mac 上如果希望紀錄 log
# * * * * * sh /path/to/test.sh >>/tmp/cron.log 2>&1
# Unix 會自動紀錄,但可以將輸出的內容加上文字方便辨識
# * * * * * sh /path/to/test.sh 2>&1 | logger -t test.sh
檢視 cron jobs 的 log
Unix
# Unix
$ sudo cat /var/log/syslog
# 也可以使用 tail 檢視
$ sudo tail -f /var/log/syslog
Mac
如果是 Mac 的話,預設是沒有紀錄的,需要的話,可以在設定 crontab 的最後加上輸出的檔案,例如:
# 將 output 和 error 分別輸出在不同檔案,且每次覆蓋
5 * * * * sh /path/to/script.sh >/tmp/stdout.log 2>/tmp/stderr.log
# 檢視 log
# sudo cat /tmp/stdout.log
# sudo cat /tmp/stderr.log
# 將 output 和 error 輸出在同一隻檔案,且不斷添加
5 * * * * sh /path/to/script.sh >>/tmp/cron.log 2>&1
# 檢視 log
# sudo cat /tmp/cron.log
其他指令
clear # 清除畫面
history # 檢視 terminal 紀錄
history | grep migration # 搜尋 含有 "migration" 的紀錄
輸入多行的 command 時,在每一行的最後使用 \
或 `,最後一行則不要輸。
=> bin/rails generate scaffold Product \
title: string description:text image_url:string price:decimal
使用 &&
可以一次執行兩個指令:
cd ~/Projects/Backup && node index.js