为什么 zip --exclude 只排除文件夹中的文件而不排除文件夹本身?

为什么 zip --exclude 只排除文件夹中的文件而不排除文件夹本身?

我在 shell 中运行以下命令bash,排除文件夹中的文件scripts/。我尝试了以下答案用于排除目录和文件的 Zip 命令但不幸的是,它对我而言不起作用。

zip_cmd="zip -r '${output_zip}' '${parent_folder}'/* \
  --exclude '${parent_folder}'/.git/* \
  --exclude '${parent_folder}'/scripts/* \
  --exclude '${parent_folder}'/$(basename "$0") \
"

但我好几天都不知道该如何排除该文件夹。该scripts文件夹仍然总是显示在生成的 zip 文件中。我试过

--exclude '${parent_folder}'/scripts/"
--exclude '${parent_folder}'/scripts"
--exclude '${parent_folder}'/scripts*"
--exclude '${parent_folder}'/scripts\*"
--exclude '${parent_folder}'/scripts/\*"
--exclude '${parent_folder}'/scripts/*"

以下是有关脚本如何执行的更多上下文,以防万一这有助于更好地理解我的问题。出于某种原因,.vscode.git文件夹被完全排除,但语法相同。怎么回事?

zip_cmd="zip -r '${output_zip}' '${parent_folder}'/* \
  --exclude '${parent_folder}'/.vscode/* \
  --exclude '${parent_folder}'/.git/* \
  --exclude '${parent_folder}'/temp/* \
  --exclude '${parent_folder}'/scripts/* \
  --exclude '${parent_folder}'/*.template.* \
  --exclude '${parent_folder}'/$(basename "$0") \
"

mapfile -t exclude_pycache < <(find "${parent_folder}" -type d -name "__pycache__")
mapfile -t exclude_executables < <(find "${parent_folder}/voxconvert-executable" -mindepth 1 -maxdepth 1 -type d -not -name "${voxconvert_version}")
exclude_paths=("${exclude_executables[@]}" "${exclude_pycache[@]}")

for path in "${exclude_paths[@]}"; do
  zip_cmd+=" --exclude \"$path/*\""
done

eval "$zip_cmd"

echo "Created zip file: $(pwd)/${output_zip}"

更新:回应@卡米尔·马乔罗夫斯基

我之所以使用字符串并执行eval而不是使用数组,是"${zip_cmd[@]}"因为使用数组时排除不起作用,因此使用字符串并执行eval是唯一的解决方案。这是我之前的尝试,但放入的提取路径exclude_paths仍然始终包含在 zip 输出中。

seven_zip_cmd=("7z" "a" "-r" "${output}" "${parent_folder}"/*)

exclude_patterns=(
  "${parent_folder}/.vscode/*"
  "${parent_folder}/.git/*"
  "${parent_folder}/temp/*"
  "${parent_folder}/*.sh"
  "${parent_folder}/$(basename "$0")"
)

mapfile -t exclude_pycache < <(find "${parent_folder}" -type d -name "__pycache__")
mapfile -t exclude_executables < <(find "${parent_folder}/voxconvert-executable" -mindepth 1 -maxdepth 1 -type d -not -name "${voxconvert_version}")
exclude_paths=("${exclude_executables[@]}" "${exclude_pycache[@]}")

for path in "${exclude_paths[@]}"; do
  # Ensure proper path formatting and add it to the exclude patterns array
  path=$(realpath "$path" --relative-to="${parent_folder}")
  exclude_patterns+=("${path}/*")
done

# Construct the exclude string within the loop
for pattern in "${exclude_patterns[@]}"; do
  seven_zip_cmd+=("-x!${pattern}")
done

# Execute the 7z command
"${seven_zip_cmd[@]}"

echo "Created 7z file: $(pwd)/${output}"

答案1

使用 7z

7z commands在 Windows 和 Linux 上都是一样的,没有什么不同。

就像在 Windows 中一样,通过在文件excluded lists内部写入会更容易。$ParentExclude.txt

根据对象进行必要的编辑。

#! /bin/bash
Parent='some path'
7z a -t7z 'Archive.7z' $Parent -xr@'Exclude.txt'

笔记:

  • $Parent:要存档的文件夹
  • -t7z:档案类型(7z、zip、rar 等)
  • archive.zip: 档案名称
  • -xr:排除递归
  • Exclude.txt:要排除的文件/文件夹列表,每个文件/文件夹用新行分隔。例如:
_pycache_
.git
logo.png
  • 外面script$parent还有Exclude.txt剧本旁边。

答案2

好吧,我明白了。事实证明,可以使用数组而不是字符串运行eval

zip_cmd=("zip" "-r" "${output_zip}" "${parent_folder}"/* \
  "--exclude" "${parent_folder}/.vscode/*" \
  "--exclude" "${parent_folder}/.git/*" \
  "--exclude" "${parent_folder}/temp/*" \
  "--exclude" "${parent_folder}/**/useful/*" \
  "--exclude" "${parent_folder}/scripts/*" \
  "--exclude" "${parent_folder}/*.template.*" \
  "--exclude" "${parent_folder}/$(basename "$0")"
)

mapfile -t exclude_pycache < <(find "${parent_folder}" -type d -name "__pycache__")
mapfile -t exclude_executables < <(find "${parent_folder}/voxconvert-executable" -mindepth 1 -maxdepth 1 -type d -not -name "${voxconvert_version}")
exclude_paths=("${exclude_executables[@]}" "${exclude_pycache[@]}")

for path in "${exclude_paths[@]}"; do
  zip_cmd+=("--exclude" "$path/*")
done

"${zip_cmd[@]}"

echo "Created zip file: $(pwd)/${output_zip}"

现在它可以正确排除脚本文件夹。因此,这种异常可能是由于使用字符串和 eval 不可靠造成的,正如 @ 所指出的那样卡米尔·马乔罗夫斯基

相关内容