Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 如何提取即时目录的名称和文件名?_Unix_Sed_Awk - Fatal编程技术网

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
...