SPo*_*eSS 15 command-line bash scripts
我如何通过目录树递归工作并对每个文件执行特定命令,并将路径、文件名、扩展名、文件大小和其他一些特定文本输出到 bash 中的单个文件。
pa4*_*080 19
虽然find解决方案简单而强大,但我决定创建一个更复杂的解决方案,即基于我几天前看到的这个有趣的函数。
1.创建名为 的可执行脚本文件,walk该文件位于/usr/local/bin可作为 shell 命令访问的位置:
sudo touch /usr/local/bin/walk
sudo chmod +x /usr/local/bin/walk
sudo nano /usr/local/bin/walk
Run Code Online (Sandbox Code Playgroud)
nano: Shift+ 中Insert用于粘贴;Ctrl+O和Enter保存;Ctrl+X退出。2、脚本内容walk为:
sudo touch /usr/local/bin/walk
sudo chmod +x /usr/local/bin/walk
sudo nano /usr/local/bin/walk
Run Code Online (Sandbox Code Playgroud)
3.说明:
walk()Zanna 在她的回答中很好地描述了该功能的主要机制。所以我将只描述新的部分。
在walk()函数中,我添加了这个循环:
#!/bin/bash
# Colourise the output
RED='\033[0;31m' # Red
GRE='\033[0;32m' # Green
YEL='\033[1;33m' # Yellow
NCL='\033[0m' # No Color
file_specification() {
FILE_NAME="$(basename "${entry}")"
DIR="$(dirname "${entry}")"
NAME="${FILE_NAME%.*}"
EXT="${FILE_NAME##*.}"
SIZE="$(du -sh "${entry}" | cut -f1)"
printf "%*s${GRE}%s${NCL}\n" $((indent+4)) '' "${entry}"
printf "%*s\tFile name:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$FILE_NAME"
printf "%*s\tDirectory:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$DIR"
printf "%*s\tName only:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$NAME"
printf "%*s\tExtension:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$EXT"
printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$SIZE"
}
walk() {
local indent="${2:-0}"
printf "\n%*s${RED}%s${NCL}\n\n" "$indent" '' "$1"
# If the entry is a file do some operations
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
# If the entry is a directory call walk() == create recursion
for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+4)); done
}
# If the path is empty use the current, otherwise convert relative to absolute; Exec walk()
[[ -z "${1}" ]] && ABS_PATH="${PWD}" || cd "${1}" && ABS_PATH="${PWD}"
walk "${ABS_PATH}"
echo
Run Code Online (Sandbox Code Playgroud)
这意味着对于每个$entry文件都将执行该函数file_specification()。
该函数file_specification()有两个部分。第一部分获取与文件相关的数据 - 名称、路径、大小等。第二部分以格式良好的形式输出数据。使用命令格式化数据printf。如果您想调整脚本,您应该阅读有关此命令的信息 - 例如这篇文章。
该函数file_specification()是一个很好的地方,您可以在其中放置应该为每个文件执行的特定命令。使用这种格式:
命令“${entry}”
或者你可以将命令的输出保存为变量,然后printf这个变量,等等:
MY_VAR="$(命令"${entry}")"
printf "%*s\t文件大小:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$MY_VAR"
或者直接printf输出命令:
printf "%*s\t文件大小:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$( command "${entry}")" 乞讨部分,称为Colourise the output,初始化printf命令中使用的几个变量,以对输出进行着色。您可以在此处找到更多相关信息。
脚本底部添加了处理绝对路径和相对路径的附加条件。
4.用法示例:
为walk当前目录运行:
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
Run Code Online (Sandbox Code Playgroud)walk为任何子目录运行:
command "${entry}"要walk为任何其他目录运行:
MY_VAR="$(command "${entry}")"
printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$MY_VAR"要根据walk输出创建文本文件:
printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$(command "${entry}")"要创建没有颜色代码的输出文件(源):
walk # You shouldn't use any argument,
walk ./ # but you can use also this format
Run Code Online (Sandbox Code Playgroud)5.使用演示:
Ser*_*nyy 14
我有点不明白为什么还没有人发布它,但bash如果您启用globstar选项并使用**glob ,它确实具有递归功能。因此,您可以编写(几乎)纯bash 脚本来使用递归 globstar,如下所示:
#!/usr/bin/env bash
shopt -s globstar
for i in ./**/*
do
if [ -f "$i" ];
then
printf "Path: %s\n" "${i%/*}" # shortest suffix removal
printf "Filename: %s\n" "${i##*/}" # longest prefix removal
printf "Extension: %s\n" "${i##*.}"
printf "Filesize: %s\n" "$(du -b "$i" | awk '{print $1}')"
# some other command can go here
printf "\n\n"
fi
done
Run Code Online (Sandbox Code Playgroud)
请注意,这里我们使用参数扩展来获取我们想要的文件名部分,我们不依赖于外部命令,除了du使用awk.
当它遍历你的目录树时,你的输出应该是这样的:
Path: ./glibc/glibc-2.23/benchtests
Filename: sprintf-source.c
Extension: c
Filesize: 326
Run Code Online (Sandbox Code Playgroud)
脚本使用的标准规则适用:确保它是可执行的chmod +x ./myscript.sh并从当前目录运行它通过./myscript.sh或将它放入~/bin并运行source ~/.profile。
Raj*_*ran 12
你可以find用来做这项工作
find /path/ -type f -exec ls -alh {} \;
Run Code Online (Sandbox Code Playgroud)
如果您只想列出所有具有大小的文件,这将对您有所帮助。
-exec将允许您对用于逐个\;解析文件的每个文件执行自定义命令或脚本,
+;如果您想连接它们(表示文件名),您可以使用。
随着find而已。
find /path/ -type f -printf "path:%h fileName:%f size:%kKB Some Text\n" > to_single_file
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用下面的代替:
find -type f -not -name "to_single_file" -execdir sh -c '
printf "%s %s %s %s Some Text\n" "$PWD" "${1#./}" "${1##*.}" $(stat -c %s "$1")
' _ {} \; > to_single_file
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25413 次 |
| 最近记录: |