定制 Linux 文件列表

LinuxLinuxBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个项目中,你将学习如何创建一个自定义的 ls 命令,以用户友好的格式显示目录大小。这个项目将帮助你理解如何使用 Zsh 脚本在 Linux 环境中检索和格式化文件信息。

👀 预览

$ cd /home/labex
$ sh newls.sh /home/labex
## 示例
drwxr-xr-x 1 labex 6B Oct 13 10:11 Code
drwxr-xr-x 1 labex 120B Oct 13 10:11 Desktop
drwxr-xr-x 1 labex 28B Sep 23 2021 golang
drwxr-xr-x 1 labex 22B Oct 23 10:17 project

🎯 任务

在这个项目中,你将学习:

  • 如何创建一个 Zsh 脚本来显示文件和目录信息
  • 如何格式化文件大小以提高可读性
  • 如何确定文件修改时间的合适日期格式
  • 如何以与 ls -lh 命令相同的格式输出文件信息

🏆 成果

完成这个项目后,你将能够:

  • 编写一个 Zsh 脚本,该脚本可以显示指定目录中文件和目录的大小
  • 格式化文件大小信息以提高可读性
  • 根据当前年份和文件的最后修改时间确定文件修改时间的合适日期格式
  • 以与 ls -lh 命令匹配的用户友好格式输出文件信息

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("`Linux`")) -.-> linux/BasicSystemCommandsGroup(["`Basic System Commands`"]) linux(("`Linux`")) -.-> linux/BasicFileOperationsGroup(["`Basic File Operations`"]) linux(("`Linux`")) -.-> linux/FileandDirectoryManagementGroup(["`File and Directory Management`"]) linux(("`Linux`")) -.-> linux/TextProcessingGroup(["`Text Processing`"]) linux(("`Linux`")) -.-> linux/SystemInformationandMonitoringGroup(["`System Information and Monitoring`"]) linux/BasicSystemCommandsGroup -.-> linux/echo("`Text Display`") linux/BasicFileOperationsGroup -.-> linux/ls("`Content Listing`") linux/FileandDirectoryManagementGroup -.-> linux/cd("`Directory Changing`") linux/TextProcessingGroup -.-> linux/awk("`Text Processing`") linux/SystemInformationandMonitoringGroup -.-> linux/date("`Date/Time Displaying`") subgraph Lab Skills linux/echo -.-> lab-301467{{"`定制 Linux 文件列表`"}} linux/ls -.-> lab-301467{{"`定制 Linux 文件列表`"}} linux/cd -.-> lab-301467{{"`定制 Linux 文件列表`"}} linux/awk -.-> lab-301467{{"`定制 Linux 文件列表`"}} linux/date -.-> lab-301467{{"`定制 Linux 文件列表`"}} end

创建 newls.sh 脚本

在这一步中,你将创建 newls.sh 脚本,该脚本将显示指定目录中所有文件和目录的大小。按照以下步骤完成此步骤:

  1. 打开文本编辑器,并在 /home/labex/project 目录中创建一个名为 newls.sh 的新文件。
  2. 在文件开头添加以下 shebang 行,以指定这是一个 Zsh 脚本:
#!/bin/zsh
  1. 在脚本开头添加一个注释块,解释其用途:
## 此脚本从指定目录中检索并格式化文件信息,以与 "ls -lh" 命令相同的格式显示。
  1. 现在,添加代码以检查是否提供了输入参数(要列出的目录)。如果没有,则显示使用消息并退出脚本:
## 检查输入参数是否为空
if [ $## -eq 0 ]; then
  echo "Usage: sh newls.sh <directory>"
  exit 1
fi
  1. 接下来,添加代码以检查指定目录是否存在。如果不存在,则显示错误消息并退出脚本:
## 检查目录是否存在
if [! -d "$1" ]; then
  echo "Directory $1 does not exist."
  exit 1
fi

检索并格式化文件信息

在这一步中,你将添加代码,从指定目录中检索文件和目录信息,并以与 ls -lh 命令相同的方式格式化输出。按照以下步骤完成此步骤:

  1. 使用 ls 命令检索指定目录中文件和目录的详细信息,并将输出存储在 ls_output 变量中:
## 使用ls命令检索文件和目录的详细信息,然后逐行处理输出
ls_output=$(ls -l --time-style="+%b %d %Y %H:%M" "$1" | tail -n +2)
  1. 添加一个 while 循环来处理 ls_output 的每一行,并提取必要的信息:
## 处理ls输出的每一行
while IFS= read -r line; do
  ## 去除每行末尾的空白字符
  line=$(echo "$line" | sed 's/[[:space:]]*$//')

  ## 解析每行的每个字段
  permissions=$(echo "$line" | awk '{print $1}')
  link_count=$(echo "$line" | awk '{print $2}')
  owner=$(echo "$line" | awk '{print $3}')
  size=$(echo "$line" | awk '{print $5}')
  month=$(echo "$line" | awk '{print $6}')
  day=$(echo "$line" | awk '{print $7}')
  year=$(echo "$line" | awk '{print $8}')
  time=$(echo "$line" | awk '{print $9}')
  name=$(echo "$line" | awk '{print $10}')
  1. 添加代码以格式化文件大小,使其更具可读性:
## 格式化文件大小以提高可读性
if [[ $size =~ ^[0-9]+$ ]]; then
  ## 如果大小是一个数字,则进行格式化
  if ((size < 1024)); then
    size_formatted="${size}B"
  elif ((size < 1024 ** 2)); then
    size_formatted="$(printf "%.1f" $(echo "scale=2; $size / 1024" | bc))K"
  elif ((size < 1024 ** 3)); then
    size_formatted="$(printf "%.1f" $(echo "scale=2; $size / (1024**2)" | bc))M"
  else
    size_formatted="$(printf "%.1f" $(echo "scale=2; $size / (1024**3)" | bc))G"
  fi
else
  ## 如果大小不能解析为数字,则保持原样
  size_formatted="$size"
fi
  1. 添加代码以根据文件的修改时间确定合适的日期格式:
current_year=$(date +"%Y")

## 从修改日期中提取年、月、日
file_year=$(echo "$year" | cut -d' ' -f3)
file_month=$(echo "$month" | cut -d' ' -f1)
file_day=$(echo "$day" | cut -d' ' -f1)

## 将月份中的前导零转换为十进制格式
file_month=$(echo "$file_month" | sed 's/^0//')

## 获取文件最后修改的时间戳
file_modified=$(date -d "$month $day $year" +"%s")

## 获取六个月前的时间戳
six_months_ago=$(date -d "6 months ago" +"%s")

## 计算当前时间与文件最后修改时间之间的秒数差
time_diff=$(($(date +"%s") - file_modified))

if ((file_year == current_year)); then
  ## 如果文件的年份与当前年份相同
  if ((time_diff >= six_months_ago)); then
    ## 超过六个月前,显示完整日期:月 日 年
    formatted_date="$month $day $year"
  else
    ## 在过去六个月内,显示日期和时间:月 日 HH:MM
    formatted_date="$month $day $time"
  fi
else
  ## 如果文件的年份与当前年份不同,显示完整日期:月 日 年
  formatted_date="$month $day $year"
fi
  1. 最后,添加代码以输出格式化后的文件信息:
  ## 输出格式包括根据条件定制的日期格式化
  printf "%-12s %-5s %-8s %-8s %s %s %-15s %s\n" "$permissions" "$link_count" "$owner" "$size_formatted" "$formatted_date" "$name"
done <<< "$ls_output"

完整的 newls.sh 脚本现在已准备好。你可以保存文件并继续下一步。

测试 newls.sh 脚本

在这一步中,你将测试 newls.sh 脚本,以确保它按预期工作。按照以下步骤完成此步骤:

  1. 打开终端并导航到 /home/labex/project 目录。
  2. /home/labex 目录作为参数运行 newls.sh 脚本:
sh newls.sh /home/labex
  1. 验证输出是否与挑战描述中所示的预期格式匹配:
drwxr-xr-x 1 labex 6B Oct 13 10:11 Code
drwxr-xr-x 1 labex 120B Oct 13 10:11 Desktop
drwxr-xr-x 1 labex 28B Sep 23 2021 golang
drwxr-xr-x 1 labex 22B Oct 23 10:17 project
  1. 如果输出与预期格式匹配,则你的 newls.sh 脚本工作正常。如果不匹配,请检查脚本并进行必要的更正。

恭喜!你已成功完成该项目,并创建了一个自定义的 ls 命令,该命令以用户友好的格式显示目录大小。

✨ 查看解决方案并练习

总结

恭喜!你已完成此项目。你可以在 LabEx 中练习更多实验以提升你的技能。

您可能感兴趣的其他 Linux 教程