Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vIu5T-0022Dm-2U for pgsql-docs@arkaria.postgresql.org; Tue, 11 Nov 2025 19:31:30 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vIu5R-007IA5-1P for pgsql-docs@arkaria.postgresql.org; Tue, 11 Nov 2025 19:31:29 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vIu5R-007I9x-0W for pgsql-docs@lists.postgresql.org; Tue, 11 Nov 2025 19:31:29 +0000 Received: from momjian.us ([72.94.173.45]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vIu5K-006azB-2t for pgsql-docs@lists.postgresql.org; Tue, 11 Nov 2025 19:31:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=momjian.us; s=2025010100; h=Content-Type:MIME-Version:Message-ID:Subject:To:From:Date: Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: In-Reply-To:References; bh=YJLeaLejZjjP993LzcUb1UJBS4bnCMpFqb2GTMn6lIA=; b=FI 9jLNL5SHRK8QaT6x6e6HjnsuPTJfikrIFCTpG00WImn0arJGnbJzksYV5vbvwVeCJkesqWCpiTvbJ zAVz56FaM8wz/m6jntvBEHidSgPHxF1YajmOrqbaIKqbtA0g503kxWWVtP0tad7H80rzy2Q0pL+1T BF2Do/64gDJ3izrL47lwb140aBksWGPWfIixp2z14vvAdy9x5fBzTuS1GNwZSPQvMaQAf5ONEtg36 1gukKh19Jyf1y0T8z4yrx8a9BX2hNFP3XBQP7GgcerqOgzlwH7ALMKlF8kXItwYl0zc8T98aZCY9i RfuMGhOaZSzOGf7S4TV11auVKvFxXiKQ==; Received: from bruce by momjian.us with local (Exim 4.98.2) (envelope-from ) id 1vIu5J-0000000DjnB-28wG for pgsql-docs@lists.postgresql.org; Tue, 11 Nov 2025 14:31:21 -0500 Date: Tue, 11 Nov 2025 14:31:21 -0500 From: Bruce Momjian To: PostgreSQL-documentation Subject: Quoting of *_command arguments Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="dM+X3SQa1vngvCfs" Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --dM+X3SQa1vngvCfs Content-Type: text/plain; charset=us-ascii Content-Disposition: inline We inconsistently double-quote the "%f" and "%p" arguments of "archive_command" and "restore_command". Paths with spaces or special characters, especially directory names in these cases, would need double-quotes. This patch adds double-quotes to all instances. I can also go the other way and remove them all, but we should be consistent. -- Bruce Momjian https://momjian.us EDB https://enterprisedb.com Do not let urgent matters crowd out time for investment in the future. --dM+X3SQa1vngvCfs Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="command.diff" diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 5f7489afbd1..168444eccc5 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -627,7 +627,7 @@ tar -cf backup.tar /usr/local/pgsql/data character in the command. The simplest useful command is something like: -archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # Unix +archive_command = 'test ! -f "/mnt/server/archivedir/%f" && cp "%p" "/mnt/server/archivedir/%f"' # Unix archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows which will copy archivable WAL segments to the directory @@ -1294,7 +1294,7 @@ SELECT * FROM pg_backup_stop(wait_for_archive => true); character in the command. The simplest useful command is something like: -restore_command = 'cp /mnt/server/archivedir/%f %p' +restore_command = 'cp "/mnt/server/archivedir/%f" "%p"' which will copy previously archived WAL segments from the directory /mnt/server/archivedir. Of course, you can use something @@ -1493,11 +1493,11 @@ restore_command = 'cp /mnt/server/archivedir/%f %p' If archive storage size is a concern, you can use gzip to compress the archive files: -archive_command = 'gzip < %p > /mnt/server/archivedir/%f.gz' +archive_command = 'gzip < "%p" > "/mnt/server/archivedir/%f.gz"' You will then need to use gunzip during recovery: -restore_command = 'gunzip < /mnt/server/archivedir/%f.gz > %p' +restore_command = 'gunzip < "/mnt/server/archivedir/%f.gz" > "%p"' diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 683f7c36f46..bd925e027b9 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -4059,7 +4059,7 @@ include_dir 'conf.d' names that are not present in the archive; it must return nonzero when so asked. Examples: -restore_command = 'cp /mnt/server/archivedir/%f "%p"' +restore_command = 'cp "/mnt/server/archivedir/%f" "%p"' restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows An exception is that if the command was terminated by a signal (other diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml index 742deb037b7..ade5995dd7a 100644 --- a/doc/src/sgml/high-availability.sgml +++ b/doc/src/sgml/high-availability.sgml @@ -745,7 +745,7 @@ protocol to make nodes agree on a serializable transactional order. A simple example of configuration is: primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass options=''-c wal_sender_timeout=5000''' -restore_command = 'cp /path/to/archive/%f %p' +restore_command = 'cp "/path/to/archive/%f" "%p"' archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r' diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index f62b61967ef..0161ad2feda 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -283,7 +283,7 @@ #archive_command = '' # command to use to archive a WAL file # placeholders: %p = path of file to archive # %f = file name only - # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' + # e.g. 'test ! -f "/mnt/server/archivedir/%f" && cp "%p" "/mnt/server/archivedir/%f"' #archive_timeout = 0 # force a WAL file switch after this # number of seconds; 0 disables @@ -294,7 +294,7 @@ #restore_command = '' # command to use to restore an archived WAL file # placeholders: %p = path of file to restore # %f = file name only - # e.g. 'cp /mnt/server/archivedir/%f %p' + # e.g. 'cp "/mnt/server/archivedir/%f" "%p"' #archive_cleanup_command = '' # command to execute at every restartpoint #recovery_end_command = '' # command to execute at completion of recovery --dM+X3SQa1vngvCfs--