有没有办法列出文件夹中的文件?
就像是:
select * from pg_ls_dir('/home/christian')
Run Code Online (Sandbox Code Playgroud)
我试过pg_ls_dir但是,根据文件:
只能
log_directory访问数据库集群目录中的文件.使用群集目录中文件的相对路径,以及与log_directory日志文件的配置设置匹配的路径.这些功能的使用仅限于超级用户.
我需要列出postgres目录之外的文件夹中的文件,类似于它的工作方式COPY.
使用PostgreSQL 9.3,可以避免安装语言扩展的开销:
DROP TABLE IF EXISTS files;
CREATE TABLE files(filename text);
COPY files FROM PROGRAM 'find /usr/bin -maxdepth 1 -type f -printf "%f\n"';
SELECT * FROM files ORDER BY filename ASC;
Run Code Online (Sandbox Code Playgroud)
创建一个具有2000分+排在81毫秒我的机器上,从表[到zip.
通常,该COPY命令需要超级用户权限.由于文件系统的路径是硬编码的(即,不是来自用户的未经过计算的值),因此首先使用超级用户帐户(例如postgres)定义函数不会造成很大的安全风险,如下所示:
CREATE OR REPLACE FUNCTION files()
RETURNS SETOF text AS
$BODY$
BEGIN
SET client_min_messages TO WARNING;
DROP TABLE IF EXISTS files;
CREATE TEMP TABLE files(filename text);
COPY files FROM PROGRAM 'find /usr/bin -maxdepth 1 -type f -printf "%f\n"';
RETURN QUERY SELECT * FROM files ORDER BY filename ASC;
END;
$BODY$
LANGUAGE plpgsql SECURITY DEFINER;
Run Code Online (Sandbox Code Playgroud)
使用非超级用户帐户登录PostgreSQL,然后:
SELECT * FROM files();
Run Code Online (Sandbox Code Playgroud)
应返回相同的结果列表,不会出现任何安全违规错误.
该SECURITY DEFINER告诉PostgreSQL的到被用来创建功能的帐户的作用下运行的功能.由于它是使用超级用户角色创建的,因此无论执行命令的角色如何,它都将以超级用户权限执行.
该SET client_min_messages TO WARNING;告诉PostgreSQL的打压消息,如果该表不能被丢弃.可以删除这一行.
将CREATE TEMP TABLE用于创建并不需要坚持一段时间的表.如果需要永久表,请删除TEMP修饰符.
该'find...'命令也可以/usr/bin/find只列出files(type -f)并仅显示文件名,而前导路径每行只分隔一个文件名(-printf "%f\n").最后,-maxdepth 1将文件搜索限制为仅指定的目录,而不搜索任何子目录.有关详细信息,请参见find的手册页.
这种方法的一个缺点是似乎没有办法参数化要执行的命令.似乎PostgreSQL要求它是文本字符串,而不是表达式语句.也许这是最好的,因为它阻止允许执行任意命令.你看到的是你执行的.
它通常对SQL客户端没用.
无论如何,你需要实现它,这是脚本语言的典型用例plperlu.例:
CREATE FUNCTION nosecurity_ls(text) RETURNS setof text AS $$
opendir(my $d, $_[0]) or die $!;
while (my $f=readdir($d)) {
return_next($f);
}
return undef;
$$ language plperlu;
Run Code Online (Sandbox Code Playgroud)
除了限制之外,这相当于系统管理功能中pg_ls_dir(text)提到的功能.
=> select * from nosecurity_ls('/var/lib/postgresql/9.1/main') as ls;
Run Code Online (Sandbox Code Playgroud)
ls
-----------------
pg_subtrans
pg_serial
pg_notify
pg_clog
pg_multixact
..
base
pg_twophase
etc...
这个答案的扩展版本,函数ls_files_extended:
-- Unfortunately that variant only allow use hardcoded path
-- To use user parameter we will use dynamic EXECUTE.
-- Return also file size and allow filtering
--
-- @param path text. Filesystem path for read to
-- @param filter text (default null meaning return all). Where condition to filter files. F.e.: $$filename LIKE '0%'$$
-- @param sort text (default filename).
--
-- Examples of use:
-- 1) Simple call, return all files, sort by filename:
-- SELECT * FROM ls_files_extended('/pg_xlog.archive')
-- 2) Return all, sort by filesize:
-- SELECT * FROM ls_files_extended('/pg_xlog.archive', null, 'size ASC')
-- 3) Use filtering and sorting:
-- SELECT * FROM ls_files_extended('/pg_xlog.archive', 'filename LIKE ''0%''', 'size ASC')
-- or use $-quoting for easy readability:
-- SELECT * FROM ls_files_extended('/pg_xlog.archive', $$filename LIKE '0%'$$, 'size ASC')
CREATE OR REPLACE FUNCTION ls_files_extended(path text, filter text default null, sort text default 'filename')
RETURNS TABLE(filename text, size bigint) AS
$BODY$
BEGIN
SET client_min_messages TO WARNING;
CREATE TEMP TABLE _files(filename text, size bigint) ON COMMIT DROP;
EXECUTE format($$COPY _files FROM PROGRAM 'find %s -maxdepth 1 -type f -printf "%%f\t%%s\n"'$$, path);
RETURN QUERY EXECUTE format($$SELECT * FROM _files WHERE %s ORDER BY %s $$, concat_ws(' AND ', 'true', filter), sort);
END;
$BODY$ LANGUAGE plpgsql SECURITY DEFINER;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10250 次 |
| 最近记录: |