03 文件和目录操作

学习目标

  • 能新建文件和目录。
  • 能复制、移动、重命名和删除文件。
  • 能查看文件类型和文件详细状态。

命令总览

命令用途含义基本用法例子
touch创建空文件或更新时间如果文件不存在就创建,存在则更新时间戳touch 文件名touch notes.txt
mkdir创建目录make directory,创建文件夹mkdir [选项] 目录名mkdir -p logs/2026
cp复制文件或目录copy,把源复制到目标cp 源 目标cp a.txt b.txt
mv移动或重命名move,把源移动到目标,也可用于改名mv 源 目标mv old.txt new.txt
rm删除文件或目录remove,删除指定路径rm 文件rm old.txt
file判断文件类型根据内容判断文件格式file 文件file app.log
stat查看文件详细信息显示大小、权限、时间等元数据stat 文件stat app.log

常用场景

下面是一段完整的受控实验,不依赖名为 project 的既有目录。它创建唯一临时目录、核对绝对路径与所有权,再演示创建、复制、移动和删除一个明确文件:

if [ "$(id -u)" -eq 0 ]; then
  printf 'do not run this lab as root\n' >&2
  exit 1
fi
 
lab_root=$(realpath -e -- "${TMPDIR:-/tmp}") || exit 1
home_real=$(realpath -e -- "${HOME:?HOME is required}") || exit 1
current_real=$(pwd -P)
paths_overlap_tree() {
  if [ "$1" = '/' ] || [ "$2" = '/' ]; then
    return 0
  fi
  case "$1/" in "$2/"*) return 0 ;; esac
  case "$2/" in "$1/"*) return 0 ;; esac
  return 1
}
if [ "$lab_root" = '/' ] \
    || paths_overlap_tree "$lab_root" "$home_real" \
    || paths_overlap_tree "$lab_root" "$current_real"; then
  printf 'unsafe lab root overlaps home or working tree: %s\n' "$lab_root" >&2
  exit 1
fi
 
work=$(mktemp -d "$lab_root/file-ops.XXXXXX") || exit 1
work_real=$(realpath -e -- "$work") || exit 1
case "$work_real" in
  "$lab_root"/file-ops.*) ;;
  *) printf 'unexpected work path: %s\n' "$work_real" >&2; exit 1 ;;
esac
if [ ! -O "$work" ] || [ -L "$work" ]; then
  printf 'work ownership or symlink check failed\n' >&2
  exit 1
fi
 
cd -- "$work_real" || exit 1
[ "$(pwd -P)" = "$work_real" ] || exit 1
mkdir -p -- project/data/raw project/data/processed project/logs
touch -- project/README.md
cp -- project/README.md project/README.bak.md
cp -R -- project/data project/data_backup
mv -- project/README.bak.md project/backup.md
mv -- project/backup.md project/logs/
 
target=$(realpath -e -- "$work_real/project/logs/backup.md") || exit 1
case "$target" in
  "$work_real"/project/logs/backup.md) ;;
  *) printf 'unexpected target: %s\n' "$target" >&2; exit 1 ;;
esac
printf 'delete=%s\n' "$target"
rm -- "$target"
file -- project/README.md
stat -- project/README.md
find . -maxdepth 3 -print

递归删除的签名只作参考:rm -r -- "$directory"。课程不提供可直接复制的 rm -rf,因为它会绕过部分交互和不存在文件的提示,且默认 --preserve-root 只特别保护 /,不能保护家目录、挂载点或错误变量。实验目录保留供检查,不自动递归删除。

新手注意

  • rm 删除后通常不会进回收站,执行前要确认路径。
  • rm -rf 非常危险,尤其不要对 /、~、空变量拼出来的路径使用。
  • 复制目录的 POSIX 便携选项是 cp -R;GNU 常见 -r,但脚本应按目标平台核对。
  • mv 既能移动文件,也能重命名文件;目标是已有目录时表示移动进去。
  • 使用带空格的文件名时要加引号,例如 mv "old name.txt" "new name.txt"。
  • -- 结束选项解析,可保护以 - 开头的路径;变量仍必须双引号引用。
  • 递归操作还要检查符号链接、挂载点与预期根目录;不要默认 sudo。

安全练习与验收

运行上面的完整实验,核对输出路径符合 $TMPDIR/file-ops.*、目标属于当前用户且不是符号链接。保存 pwd -P、find . -maxdepth 3 -print 和退出码;确认只删除了 project/logs/backup.md,不练递归删除。

参考资料