如何在脚本中列出具有绝对路径和空格的路径中的所有文件

如何在脚本中列出具有绝对路径和空格的路径中的所有文件

我正在编写一个脚本,它接受路径作为参数并处理路径中的所有 .mkv 文件。该路径可以是绝对路径、相对路径,甚至是单个文件。但是,我仍然需要正在迭代的文件的绝对路径。

这是我到目前为止所做的:

#!/bin/bash

path=$1
if ! [ -e "$path" ]; then
  path=$(pwd)
fi

find "$path" -type f -name '*.mkv' | sort | xargs realpath | while read file; do
  echo "Processing $file"
done

当路径和/或文件中没有空格时,此方法有效,但因空格而失败。

正确的做法是什么?

答案1

zsh

#! /bin/zsh -
for file (${${1-.}:P}/**/*.mkv(ND.))
  print -r processing $file
  • ${1-.}就像在 Bourne shell 中一样,扩展为.if $1is not set (if $#== 0; if 是一个糟糕的接口,而不是当$1is 是一个不存在的文件时,因为这会让用户感到非常惊讶)
  • ${param:P}扩展到realpath()该扩展的 。无需对每个文件执行相同的操作,因为**/不遵循符号链接并且.限定符仅选择常规的文件,所以不是符号链接。
  • **/匹配任何级别的子目录
  • N用于 nullglob、Ddotglob、.for 的Glob 限定符常规的仅有的。

答案2

您可以预处理路径本身而不是所有文件:

find "$(realpath -- "$path")" -type f -name '*.mkv' -exec printf 'Processing %s\n' {} +

替换printf为您实际想要对文件执行的任何操作。+表示每次调用可以处理多个文件;如果不是这种情况,请改用\;

答案3

同意斯蒂芬的观点,总是更喜欢-exec尝试对输出进行后处理find。如果确实需要,请始终使用-print0允许明确的文件名分隔;大多数从输入中使用文件名的工具都支持某种--null, --zero/-z-0标志,以使它们将输入解释为以 0 字节分隔。

就你而言,我可能更喜欢 zsh,但假设你想坚持使用 bash,你可以做同样的事情而不会出现任何问题。您可以省略sort,因为无论如何,通配符都是按字母顺序排列的。你可以省略find,因为 bash 也可以进行递归通配(zsh 也可以在通配时限制文件类型,在 bash 中我们实际上需要测试-f文件性),并且你可以省略,xargs因为你正在处理一个文件无论如何,一次:

#!/bin/bash
# Fail when something goes wrong!
set -e
# enable recursive globs, and don't fail when there's nothing there
shopt -s globstar
shopt -s dotglob
shopt -s nullglob

inpath="$1"
if ! [ -e "${inpath}" ]; then
  inpath="$(pwd)"
fi

for file in "${inpath}/**/*.mkv"; do
  # check whether regular file, skip if not
  [ -f "${file}" ] || continue
  fullpath="$(realpath -- "${file}")"
  echo  "Processing ${fullpath}" # Could / might prefer to use printf here instead
done

以不同的方式对事物进行排序,以防默认排序确实不是您所需要的。你需要更换

for file in "${inpath}/**/*.mkv"; do

类似的东西

unsorted=( ${inpath}/**/*.mkv )
readarray -d '' -t sorted_files < \
    <(printf '%s\0' "${unsorted[@]}" \
        | sort -z --whateveroptions \
     )
for file in "${sorted_files[@]}" ; do

readarray具有-d将分隔符设置为传递的字符串的选项;传递空字符串会使其使用零字节作为分隔符。readarray-t修剪(我们在这里不需要它,但我发现它是一个安全的默认值),sort -z使用零字节作为分隔符。"${arrayname[@]}"扩展为该数组中元素的可迭代列表,但即使元素中包含空格和换行符,也可以安全使用。

在 zsh 中,您还可以对通过通配找到的文件进行排序。尽可能使用 zsh。

相关内容