在 ~/Desktop/a/ 中,我有文件夹(名称中有空格)和 txt 文件,格式如下:
100 description of project A
100_notes.txt
200 description of project B
200_notes.txt
我想要什么:
100 description of project A
100 description of project A.txt
200 description of project B
200 description of project B.txt
这是到目前为止的脚本:
#!/bin/bash
cd ~/Desktop/a/
for i in *; do
mv "$i/${f%.txt}" "$i.txt";
done
我正在尝试使用测试文件,它会将文件夹重命名为具有 .txt 扩展名,这不是我想要的。
答案1
#!/bin/sh
for notes in ./???_notes.txt
do
if [ ! -f "$notes" ]; then
continue
fi
num=${notes%_notes.txt}
set -- "$num "*/
if [ "$#" -gt 1 ]; then
echo 'More than one directory found:' >&2
printf '\t%s\n' "$@" >&2
printf 'Skipping %s...\n' "$notes" >&2
continue
elif [ ! -d "$1" ]; then
printf 'No directory matching "%s" found\n' "$num */" >&2
printf 'Skipping %s...\n' "$notes" >&2
continue
fi
printf 'Would rename "%s" into "%s"\n' "$notes" "${1%/}.txt"
# mv -i "$notes" "${1%/}.txt"
done
该脚本将迭代NNN_notes.txt
当前目录中的所有文件。对于每个文件,提取数字NNN
(可以是任何三个字母的字符串)并用于检测任何目录调用NNN
后跟一个空格和任意字符串。
如果找到单个目录,则相应地重命名该文件(为了安全起见,实际重命名被注释掉)。如果找到多个目录或未找到目录,则会显示一条消息指出这一点。
参数替换会从 值的末尾${variable%string}
删除字符串。该命令在此脚本中使用时,会将位置参数 、等设置为与给定文件名通配模式匹配的内容(在此脚本中,我们希望该模式与一个目录完全匹配)。该值是此类位置参数的数量。string
$variable
set
$1
$2
$3
$#
按照我编写此脚本的方式,它可以由bash
和执行/bin/sh
。它不使用任何“bashisms”。
仅Abash
版本:
#!/bin/bash
shopt -s nullglob
for notes in ./???_notes.txt
do
num=${notes%_notes.txt}
dirs=( "$num "*/ )
if [ "${#dirs[@]}" -gt 1 ]; then
echo 'More than one directory found:' >&2
printf '\t%s\n' "${dirs[@]}" >&2
printf 'Skipping %s...\n' "$notes" >&2
continue
elif [ "${#dirs[@]}" -eq 0 ]; then
printf 'No directory matching "%s" found\n' "$num */" >&2
printf 'Skipping %s...\n' "$notes" >&2
continue
fi
printf 'Would rename "%s" into "%s"\n' "$notes" "${dirs[0]%/}.txt"
# mv -i "$notes" "${dirs[0]%/}.txt"
done
这里最大的区别是我们使用命名数组dirs
来保存模式的可能扩展"$num "*/
,并且我们使用nullglob
shell 选项将不匹配的文件名模式扩展为空。