Linux Bash循环-为目录中的每个现有txt文件创建一个文件夹

Linux Bash循环-为目录中的每个现有txt文件创建一个文件夹,linux,bash,shell,unix,Linux,Bash,Shell,Unix,我想组织目录中的文本文件。我试图通过bash为每个文件创建一个目录来实现这一点。当我将文件移动到其各自的新文件夹时,我想修改原始的文件名,并创建一个包含原始文件名的附加文本文件labeldinfo.txt(此文件也放在新文件夹中)。文件名更改从xxx-file\u name-aa1.txt更改为xxx-aa1.txt。第一个和最后一个-之间的任何内容都将被删除。该文件夹与文件xxx-aa1同名 test.sh(my sed语句)删除空格并将所有内容转换为小写,但最后一个- FILE_PATH="

我想组织目录中的文本文件。我试图通过bash为每个文件创建一个目录来实现这一点。当我将文件移动到其各自的新文件夹时,我想修改原始的
文件名
,并创建一个包含原始文件名的附加文本文件labeld
info.txt
(此文件也放在新文件夹中)。文件名更改从
xxx-file\u name-aa1.txt
更改为
xxx-aa1.txt
。第一个和最后一个
-
之间的任何内容都将被删除。该文件夹与文件
xxx-aa1
同名

test.sh(my sed语句)删除空格并将所有内容转换为小写,但最后一个
-

FILE_PATH="/media/sf_linux_sandbox/txt_files/"
while read -r file; do
#sed statement empty
new_name=$(echo "$file" | sed 's/^\(.*\)\(-[^-]*\)$/\L\1\E\2/; s/ *- */-/; s/^\(.*\) \+- *\([^-]*\)$/\1-\2/; s/ /_/g')
mv "$file" "$new_name"
done < <(find $FILE_PATH -maxdepth 1 -type f -name '*.txt')
期望输出:

|-- ./
|   |-- xxxx-aa1
|       |--xxx-aa1.txt
|       |--info.txt // contains name 'test_file1'
|   |-- xxxx-bb2
        |--xxx-bb2.txt
        |--info.txt // contains name 'test_file2'
电流输出

|-- ./
|   |-- xxxx-test_file-aa1
|       |--xxxx-test_file-aa1.txt
|   |-- xxxx-test_file-bb2
        |--xxxx-test_file-bb2.txt

sed
更改为

new_name=$(echo "$file" | sed -r 's/-[^-]*-/-/g')
例如:

-[^-]*-
选择两个
-
之间的字符串,sed
s
将其替换为
-

FILE_PATH="/media/sf_linux_sandbox/txt_files/"
while read -r file; do
#sed statement empty
new_name=$(echo "$file" | sed 's/^\(.*\)\(-[^-]*\)$/\L\1\E\2/; s/ *- */-/; s/^\(.*\) \+- *\([^-]*\)$/\1-\2/; s/ /_/g')
mv "$file" "$new_name"
done < <(find $FILE_PATH -maxdepth 1 -type f -name '*.txt')
您还可以使用
grep
命令获取目录名

$ echo $new_name | grep -o '^[^.]*'
xxxx-aa1
^[^.]*
选择文件名中不包含扩展名的部分

编辑

获取文件名

$ echo "xxx-test_file-aa1.txt" | grep -oP '(?<=-)[^.]*(?=-)'
test_file

$echo“xxx-test_file-aa1.txt”|grep-oP'(?您实际上可以在Bash本身中执行所有这些操作

由于您有
-maxdepth 1
,看起来您可以使用通配符循环而不是
find
,所以我也对其进行了重构

FILE_PATH="/media/sf_linux_sandbox/videos/"
for file in "$FILE_PATH"/*.mp4; do
    tmp=${file#*-}; head=${file%-"$tmp"}
    mid=${tmp%-*}; tail=${tmp#"$mid"-}
    base="${head,,}-${tail,,}"
    dir=${base%.mp4}
    mkdir -p "$dir"
    mv "$file" "$dir/$base"
    echo "$mid" >"$dir"/info.txt
done

简单地说,
${var#prefix}
扩展到
var
的值,并删除
前缀
${var%suffix}
相应地用后缀执行相同的替换。最后,
${var,,}
生成值的小写版本。然后,我们只需从这些部分组合您想要的文件名结构。

太好了!离我的目标更近了。我如何能够将介于
-
之间的内容输出到txt文件。例如
xxxx-test\u file-aa1.txt
获取
test\u file\u aa1
并输出到中的
fo.txt
对不起,我打错了,只是想抓住
-
和最后一个
-
之间的内容,所以它就是
test\u文件
。如果文件有两个以上的
-
像这样
xxxx-test\u文件1-aa1
test\u文件1
应该是
xxxx-test\u文件1-aa1
吗问题?我已经在回答中更正了。假设
xxxx-test\u文件1-aa1
是文件名,而不是
xxxx-test\u文件1-aa1
,正如您之前的评论。如果编辑错误,请指出:)您的测试用例根本不涉及小写功能。此外,您有
新的\u名称
,但随后移动到
新的\u文件
。最后,您的
查找
循环有
.mp4
文件,但您的伪示例显示了
.txt
文件。@triplee,很抱歉我也用mp4文件进行了测试,忘了恢复我的pseu为txt文件编写所有代码。非常清楚,已测试过,但如果文件名中有多个连字符
-
,则会中断。例如
xxxx-test\u file-1-aa1
不会转换为
xxxx-aa1
,而是
xxxx-1
。对于新文件夹/文件名而言,唯一重要的是第一个
-之前的内容e> 最后一个
-
.重构后的文件名可以使用任意数量的破折号(但如果破折号少于两个,则会不稳定)。作为历史参考,早期版本使用了
IFS=-
set
来分割文件名,但是硬编码正好是两个破折号。哦,不知道
IFS=-
set
正好是两个破折号。现在一切都有意义了。很好地解释了!这并不是说它们不能工作,而是重构让它成功了通过切换到前缀/后缀,代码变得更简单。好的,运行得很好,正如预期的那样。我对文件的名称格式不是很具体,现在我发现具有这种类型名称的文件有一个问题
xxxx-test\u file-caa-v3u
(结尾处有两个以上的
-
)。我做了一个
FILE_PATH="/media/sf_linux_sandbox/videos/"
for file in "$FILE_PATH"/*.mp4; do
    tmp=${file#*-}; head=${file%-"$tmp"}
    mid=${tmp%-*}; tail=${tmp#"$mid"-}
    base="${head,,}-${tail,,}"
    dir=${base%.mp4}
    mkdir -p "$dir"
    mv "$file" "$dir/$base"
    echo "$mid" >"$dir"/info.txt
done