Inb*_*ose 7 ls shell tar shell-script
我有一个要存档的目录列表。但有时它们并不都存在。
我希望能够通过提供目录列表来创建存档,它只会存档现有的,而忽略丢失的。(但如果不存在目录,仍然应该失败)
这对我很有用,因为我正在运行一些持续集成,并且一些流程创建了我想在存档中保留以备将来使用的某些工件,我知道可以创建的所有可能路径,但并不总是确定哪些路径被创建。
假设可能的路径是: here_is_a_dir here_is_another_one yet_another_dir
我通常使用以下命令创建存档:
tar -czf archive.tgz here_is_a_dir here_is_another_one yet_another_dir
如果缺少任何目录,这当然会失败。
理想情况下,它应该是一个简单的命令,不需要脚本来完成。(具体来说,仅在我的环境sh中可用,所以我不能使用任何像bash或其他人一样的花哨的外壳,但这特定于我的环境,将来可能会发生变化,我认为使用其他外壳的答案也可能很好。 )
使用 的输出ls通常是不明智和不安全的 - 请记住,空格和换行符以及其他 shell 元字符都是文件或目录名称中的有效字符。在许多情况下可以解决此问题,但这样做通常比仅使用正确的工具(即find)更费力。
所以,find改用。例如:
find . -maxdepth 1 -type d \( -name here_is_a_dir -o -name here_is_another_one \
-o -name yet_another_dir \) -exec tar cfz archive.tgz {} +
Run Code Online (Sandbox Code Playgroud)
这会-type d在当前目录 ( .) 中找到任何匹配的目录 ( ) 并将它们用作tar命令的参数。的\(到\)是一个表达式,其中每个所述子表达式的是OR-ED一起使用-o(默认,查找的谓词是AND-ED)。即它读作“maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)”。
请注意,如果没有括号强制优先,它将被解释为“maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)”,这不会返回所有现有目录的完整列表。大多数情况下,它要么什么都不返回,要么只返回 dir3,这取决于 dir1 是否存在。
如果您希望它在当前目录下的任何位置找到子目录,请删除该-maxdepth 1参数。
如果您希望目录匹配不区分大小写,请使用-iname代替-name。请注意,-nameor的参数-iname可以是模式而不是固定字符串 - 如果所需的目录名称非常相似,这很有用。例如
find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz {} +
Run Code Online (Sandbox Code Playgroud)
其-exec ....工作方式很像管道到xargs,但内置于find. 事实上,xargs如果您愿意,您可以通过将所有内容替换-exec为-print0 | xargs -0 -r tar cfz archive.tgz. 例如
find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | \
xargs -0 -r tar cfz archive.tgz
Run Code Online (Sandbox Code Playgroud)
(这使用 NUL 字符作为输出分隔符,因此与包含空格等的目录名一起使用是安全的-exec。-r如果没有输入,该选项告诉 xargs 什么都不做)
与zsh:
dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
existing_dirs=($^dirs_to_archive(/N))
if (($#existing_dirs)); then
tar -cf - -- $existing_dirs | xz > file.tar.xz
else
echo >&2 Error: none of the dirs were found
fi
Run Code Online (Sandbox Code Playgroud)
POSIX 等价物(但请注意,POSIX 命令既不是tar也不xz是 POSIX 命令)类似于:
# The list of dirs in "$@" (the only array in POSIX sh language)
set -- some/dir /some/other/dir and/more/dirs
for dir do
# remove from the array the elements that are not directories like with
# zsh's / glob qualifier above
[ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
shift
done
if [ "$#" -gt 0 ]; then
tar -cf - -- "$@" | xz > file.tar.xz
else
echo >&2 Error: none of the dirs were found
fi
Run Code Online (Sandbox Code Playgroud)
ls使用创建现有目录列表,然后通过管道传递xargs到命令,可以相对轻松地完成此操作tar。
解决方案:
ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz
分解:
ls -d只列出目录here_is_a_dir here_is_another_one yet_another_dir要检查的目录列表2> /dev/null将 stderr 通过管道传输到 /dev/null 所以我们只得到 stdout 输出(没有丢失目录)| xargs将上一个命令中的现有目录列表转换为参数tar -czf archive.tgz使用参数进行存档| 归档时间: |
|
| 查看次数: |
2400 次 |
| 最近记录: |