diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index ccd7b48108..fb3bab9494 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -98,6 +98,8 @@ static backslashResult process_command_g_options(char *first_option,
 												 bool active_branch,
 												 const char *cmd);
 static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_getenv(PsqlScanState scan_state, bool active_branch,
+										   const char *cmd);
 static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
@@ -348,6 +350,8 @@ exec_command(const char *cmd,
 		status = exec_command_g(scan_state, active_branch, cmd);
 	else if (strcmp(cmd, "gdesc") == 0)
 		status = exec_command_gdesc(scan_state, active_branch);
+	else if (strcmp(cmd, "getenv") == 0)
+		status = exec_command_getenv(scan_state, active_branch, cmd);
 	else if (strcmp(cmd, "gexec") == 0)
 		status = exec_command_gexec(scan_state, active_branch);
 	else if (strcmp(cmd, "gset") == 0)
@@ -1481,6 +1485,43 @@ exec_command_gdesc(PsqlScanState scan_state, bool active_branch)
 	return status;
 }
 
+/*
+ * \getenv -- set variable from environment variable
+ */
+static backslashResult
+exec_command_getenv(PsqlScanState scan_state, bool active_branch,
+					const char *cmd)
+{
+	bool		success = true;
+
+	if (active_branch)
+	{
+		char	   *myvar = psql_scan_slash_option(scan_state,
+												   OT_NORMAL, NULL, false);
+		char	   *envvar = psql_scan_slash_option(scan_state,
+													OT_NORMAL, NULL, false);
+
+		if (!myvar || !envvar)
+		{
+			pg_log_error("\\%s: missing required argument", cmd);
+			success = false;
+		}
+		else
+		{
+			char	   *envval = getenv(envvar);
+
+			if (envval && !SetVariable(pset.vars, myvar, envval))
+				success = false;
+		}
+		free(myvar);
+		free(envvar);
+	}
+	else
+		ignore_slash_options(scan_state);
+
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
+}
+
 /*
  * \gexec -- send query and execute each field of result
  */
diff --git a/src/test/regress/input/copy.source b/src/test/regress/input/copy.source
index 8acb516801..ad42d02a22 100644
--- a/src/test/regress/input/copy.source
+++ b/src/test/regress/input/copy.source
@@ -2,14 +2,20 @@
 -- COPY
 --
 
+-- directory paths are passed to us in environment variables
+\getenv ABS_SRCDIR ABS_SRCDIR
+\getenv ABS_BUILDDIR ABS_BUILDDIR
+
 -- CLASS POPULATION
 --	(any resemblance to real life is purely coincidental)
 --
-COPY aggtest FROM '@abs_srcdir@/data/agg.data';
+COPY aggtest FROM :'ABS_SRCDIR'
+	'/data/agg.data';
 
 COPY onek FROM '@abs_srcdir@/data/onek.data';
 
-COPY onek TO '@abs_builddir@/results/onek.data';
+COPY onek TO :'ABS_BUILDDIR'
+	'/results/onek.data';
 
 DELETE FROM onek;
 
diff --git a/src/test/regress/input/create_function_0.source b/src/test/regress/input/create_function_0.source
index f47f635789..122771fda8 100644
--- a/src/test/regress/input/create_function_0.source
+++ b/src/test/regress/input/create_function_0.source
@@ -2,11 +2,17 @@
 -- CREATE_FUNCTION_0
 --
 
+-- directory path and DLSUFFIX are passed to us in environment variables
+\getenv LIBDIR LIBDIR
+\getenv DLSUFFIX DLSUFFIX
+
 -- Create a bunch of C functions that will be used by later tests:
 
 CREATE FUNCTION check_primary_key ()
 	RETURNS trigger
-	AS '@libdir@/refint@DLSUFFIX@'
+	AS :'LIBDIR'
+	'/refint'
+	:'DLSUFFIX'
 	LANGUAGE C;
 
 CREATE FUNCTION check_foreign_key ()
diff --git a/src/test/regress/output/copy.source b/src/test/regress/output/copy.source
index 25bdec6c60..d21b150d1a 100644
--- a/src/test/regress/output/copy.source
+++ b/src/test/regress/output/copy.source
@@ -1,12 +1,17 @@
 --
 -- COPY
 --
+-- directory paths are passed to us in environment variables
+\getenv ABS_SRCDIR ABS_SRCDIR
+\getenv ABS_BUILDDIR ABS_BUILDDIR
 -- CLASS POPULATION
 --	(any resemblance to real life is purely coincidental)
 --
-COPY aggtest FROM '@abs_srcdir@/data/agg.data';
+COPY aggtest FROM :'ABS_SRCDIR'
+	'/data/agg.data';
 COPY onek FROM '@abs_srcdir@/data/onek.data';
-COPY onek TO '@abs_builddir@/results/onek.data';
+COPY onek TO :'ABS_BUILDDIR'
+	'/results/onek.data';
 DELETE FROM onek;
 COPY onek FROM '@abs_builddir@/results/onek.data';
 COPY tenk1 FROM '@abs_srcdir@/data/tenk.data';
diff --git a/src/test/regress/output/create_function_0.source b/src/test/regress/output/create_function_0.source
index 342bc40e11..b602543433 100644
--- a/src/test/regress/output/create_function_0.source
+++ b/src/test/regress/output/create_function_0.source
@@ -1,10 +1,15 @@
 --
 -- CREATE_FUNCTION_0
 --
+-- directory path and DLSUFFIX are passed to us in environment variables
+\getenv LIBDIR LIBDIR
+\getenv DLSUFFIX DLSUFFIX
 -- Create a bunch of C functions that will be used by later tests:
 CREATE FUNCTION check_primary_key ()
 	RETURNS trigger
-	AS '@libdir@/refint@DLSUFFIX@'
+	AS :'LIBDIR'
+	'/refint'
+	:'DLSUFFIX'
 	LANGUAGE C;
 CREATE FUNCTION check_foreign_key ()
 	RETURNS trigger
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 2c8a600bad..a8c877aa2e 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -509,6 +509,12 @@ convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const ch
 	/* We might need to replace @testtablespace@ */
 	snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
 
+	setenv("ABS_SRCDIR", inputdir, 1);
+	setenv("ABS_BUILDDIR", outputdir, 1);
+	setenv("TESTTABLESPACE", testtablespace, 1);
+	setenv("LIBDIR", dlpath, 1);
+	setenv("DLSUFFIX", DLSUFFIX, 1);
+
 	/* finally loop on each file and do the replacement */
 	for (name = names; *name; name++)
 	{
