Unix 如何提取即时目录的名称和文件名?
我有一个文件,其完整路径如下Unix 如何提取即时目录的名称和文件名?,unix,sed,awk,Unix,Sed,Awk,我有一个文件,其完整路径如下 /a/b/c/d/filename.txt 如果我对它做了一次修改,就会得到filename.txt。但是这个文件名不是很唯一 因此,如果我能将文件名提取为d_filename.txtI.e,那就更好了 {immediate directory}_{basename result} 我如何才能达到这个结果? file="/path/to/filename" echo $(basename $(dirname "$file")_$(basename "$file"
/a/b/c/d/filename.txt
如果我对它做了一次修改,就会得到filename.txt
。但是这个文件名不是很唯一
因此,如果我能将文件名提取为d_filename.txt
I.e,那就更好了
{immediate directory}_{basename result}
我如何才能达到这个结果?
file="/path/to/filename"
echo $(basename $(dirname "$file")_$(basename "$file"))
或
不需要调用外部命令
s="/a/b/c/d/filename.txt"
t=${s%/*}
t=${t##*/}
filename=${t}_${s##*/}
这段代码将递归地搜索整个层次结构,从运行脚本的目录开始。我对循环进行了编码,这样它就可以处理您抛出的任何文件名;带有空格、换行符等的文件名 *注意**:循环当前写入而不包含此脚本所在目录中的任何文件,它只查看其下方的子目录。这样做是因为这是确保脚本在处理过程中不包含自身的最简单方法。如果出于某种原因,必须包含脚本所在的目录,则可以对其进行更改以适应此情况 代码 输出 例如:
/a/1/b/c/d/file.txt
/a/2/b/c/d/file.txt
限定file.txt
并避免冲突的唯一可靠方法是将整个路径构建到新文件名中,例如
/a/1/b/c/d/file.txt -> a_1_b_c_d_file.txt
/a/2/b/c/d/file.txt -> a_2_b_c_d_file.txt
如果您确信所有文件都会使用开头部分,例如,如果您知道所有文件都位于上述目录/a
下,则可以跳过开头部分:
/a/1/b/c/d/file.txt -> 1_b_c_d_file.txt
/a/2/b/c/d/file.txt -> 2_b_c_d_file.txt
要在每个文件的基础上实现这一点:
# file="/path/to/filename.txt"
new_file="`echo \"$file\" | sed -e 's:^/::' -e 's:/:_:g'`"
# new_file -> path_to_filename.txt
假设您希望在目录及其子目录中递归执行此操作:
# dir = /a/b
( cd "$dir" && find . | sed -e 's:^\./::' | while read file ; do
new_file="`echo \"$file\" | sed -e 's:/:_:g'`"
echo "rename $dir/$file to $new_file"
done )
输出:
rename /a/b/file.txt to file.txt
rename /a/b/c/file.txt to c_file.txt
rename /a/b/c/e/file.txt to c_e_file.txt
rename /a/b/d/e/file.txt to d_e_file.txt
...
上述文件具有很高的可移植性,基本上可以在任何Unix系统上运行,
sh
(包括bash
,ksh
等)我在文件夹层次结构中有很多不同的文件,所以我事先不知道文件夹的名称。@eSKay:偶然发现了这个老问题,但我想指出,这个答案并不取决于事先知道名字;只需将任一解决方案中的/path/更改为/filename
,然后使用文件路径的其余部分即可。如果要对许多文件执行此操作,则需要提供更多信息。比如脚本应该在哪个目录中运行?另外,创建新文件名后,您希望如何处理它?将其分配给var?重命名原始文件?我在根目录下。是的,我想把它分配给程序中的一个变量。问题是,修补程序甚至可能是/a/b/c/anotherfile.txt
,也就是说,这些文件位于第四层次结构中,这一点并不是固定的。代码已更新以反映这一点。请在此处查看我的答案-->这并不总是有效的/a/1/b/c/d/baz和/a/2/b/c/d/baz将产生重复的名称“d_baz”。这是真的,但我想说,你的评论比我更适合OP,因为我的代码符合所述要求。
/a/1/b/c/d/file.txt -> a_1_b_c_d_file.txt
/a/2/b/c/d/file.txt -> a_2_b_c_d_file.txt
/a/1/b/c/d/file.txt -> 1_b_c_d_file.txt
/a/2/b/c/d/file.txt -> 2_b_c_d_file.txt
# file="/path/to/filename.txt"
new_file="`echo \"$file\" | sed -e 's:^/::' -e 's:/:_:g'`"
# new_file -> path_to_filename.txt
# dir = /a/b
( cd "$dir" && find . | sed -e 's:^\./::' | while read file ; do
new_file="`echo \"$file\" | sed -e 's:/:_:g'`"
echo "rename $dir/$file to $new_file"
done )
rename /a/b/file.txt to file.txt
rename /a/b/c/file.txt to c_file.txt
rename /a/b/c/e/file.txt to c_e_file.txt
rename /a/b/d/e/file.txt to d_e_file.txt
...