BASH:对具有疯狂名称的文件数组进行排序

发布于 2024-11-27 22:46:53 字数 1072 浏览 0 评论 0原文

问题:

在使用函数对数组进行操作之前需要对数组进行排序。

首先,数组加载文件:

unset a i
counter=1
while IFS= read -r -d $'\0' file; do
    a[i++]="$file"
done < <(find $DIR -type f -print0)

接下来,数组的每个成员都被发送到函数

for f in "${a[@]}"
do
   func_hash "$f"
   [ $(expr $counter % 20) -eq 0 ] && printf "="
   counter=$((counter + 1))
done

不知何故,需要将排序放入上面的 for 循环中。看过 通过关于排序数组的 SO 帖子,但不知何故我疯狂的文件名 当我尝试进行排序时会引起问题。

有想法吗?

谢谢!

Bubnoff

更新:这是带有排序的代码:

while IFS= read -r -d $'\0' file; do
    func_hash "$file"
    [ $(expr $counter % 20) -eq 0 ] && printf "="
    counter=$((counter + 1))
done < <(find $DIR -type f -print0 | sort -z +1 -1)

它按完整路径而不是文件名排序。关于如何的任何想法 考虑到函数需要路径,按文件名排序?

更新2:决定妥协。

我的主要目标是避免使用排序临时文件。 GNU排序可以写回原来的 文件及其“-o”选项,所以现在我可以:

sort -o $OUT -t',' -k 1 $OUT

任何人都有一个更“优雅”的解决方案(无论这意味着什么)。

已解决请参阅下面 jw013 的回答。谢谢伙计!

Problem:

Need to sort array before operating on them with function.

First, array is loaded with files:

unset a i
counter=1
while IFS= read -r -d 

Next, each member of array is sent to function

for f in "${a[@]}"
do
   func_hash "$f"
   [ $(expr $counter % 20) -eq 0 ] && printf "="
   counter=$((counter + 1))
done

Somehow a sort needs to be thrown into the above for loop. Have looked
through the SO posts on sorting arrays but somehow my crazy file names
cause issues when I try to tack on a sort.

Ideas?

Thanks!

Bubnoff

UPDATE: Here's code with sort:

while IFS= read -r -d 

It's sorting by full path rather than file name. Any ideas on how to
sort by file name given that the path is needed for the function?

UPDATE 2: Decided to compromise.

My main goal was to avoid temp files using sort. GNU sort can write back to the original
file with its '-o' option so now I can:

sort -o $OUT -t',' -k 1 $OUT

Anyone have a more 'elegant' solution ( whatever that means ).

SOLVED See jw013's answer below. Thanks man!

\0' file; do a[i++]="$file" done < <(find $DIR -type f -print0)

Next, each member of array is sent to function


Somehow a sort needs to be thrown into the above for loop. Have looked
through the SO posts on sorting arrays but somehow my crazy file names
cause issues when I try to tack on a sort.

Ideas?

Thanks!

Bubnoff

UPDATE: Here's code with sort:


It's sorting by full path rather than file name. Any ideas on how to
sort by file name given that the path is needed for the function?

UPDATE 2: Decided to compromise.

My main goal was to avoid temp files using sort. GNU sort can write back to the original
file with its '-o' option so now I can:


Anyone have a more 'elegant' solution ( whatever that means ).

SOLVED See jw013's answer below. Thanks man!

\0' file; do func_hash "$file" [ $(expr $counter % 20) -eq 0 ] && printf "=" counter=$((counter + 1)) done < <(find $DIR -type f -print0 | sort -z +1 -1)

It's sorting by full path rather than file name. Any ideas on how to
sort by file name given that the path is needed for the function?

UPDATE 2: Decided to compromise.

My main goal was to avoid temp files using sort. GNU sort can write back to the original
file with its '-o' option so now I can:

Anyone have a more 'elegant' solution ( whatever that means ).

SOLVED See jw013's answer below. Thanks man!

\0' file; do a[i++]="$file" done < <(find $DIR -type f -print0)

Next, each member of array is sent to function

Somehow a sort needs to be thrown into the above for loop. Have looked
through the SO posts on sorting arrays but somehow my crazy file names
cause issues when I try to tack on a sort.

Ideas?

Thanks!

Bubnoff

UPDATE: Here's code with sort:

It's sorting by full path rather than file name. Any ideas on how to
sort by file name given that the path is needed for the function?

UPDATE 2: Decided to compromise.

My main goal was to avoid temp files using sort. GNU sort can write back to the original
file with its '-o' option so now I can:

Anyone have a more 'elegant' solution ( whatever that means ).

SOLVED See jw013's answer below. Thanks man!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

习ぎ惯性依靠 2024-12-04 22:46:53

编辑

while IFS= read -r -d/ && read -r -d '' file; do
    a[i++]="$file"
done < <(find "$DIR" -type f -printf '%f/%p\0' | sort -z -t/ -k1 )

基本原理:

  • 我假设 / 永远不是文件名中的合法字符(这在大多数 *nix 文件系统上似乎是合理的,因为它是路径分隔符)。
  • -printf 用于打印不带前导目录的文件名,然后打印带路径的完整文件名,以 / 分隔。排序发生在由 / 分隔的第一个字段上,该字段应该是不带路径的完整文件名。
  • read 被修改为首先使用 / 作为分隔符来抛出无路径文件名。

旁注

任何 POSIX shell 都应该支持模运算符作为其算术扩展的一部分。您可以在第二个循环中将 line 替换为对外部命令 expr 的调用

[ $(( counter % 20 )) -eq 0 ] ...

EDIT

while IFS= read -r -d/ && read -r -d '' file; do
    a[i++]="$file"
done < <(find "$DIR" -type f -printf '%f/%p\0' | sort -z -t/ -k1 )

Rationale:

  • I make the assumption that / is never a legal character within a file name (which seems reasonable on most *nix filesystems since it is the path separator).
  • The -printf is used to print the file name without leading directories, then then full file name with path, separated by /. The sort takes place on the first field separated by / which should be the full file name without path.
  • The read is modified to first use / as a delimiter to throw out the pathless file name.

side note

Any POSIX shell should support the modulo operator as part of its arithmetic expansion. You can replace line with the call to external command expr in the second loop with

[ $(( counter % 20 )) -eq 0 ] ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文