I get the error message...

could not change directory to "/home/corey/scripts": Permission denied

... when I run the following script ...

sudo -u postgres psql < setup_dev_db.sql
read -rsp $'Press any key to continue...\n' -n 1 key

... the contents of setup_dev_db.sql are executed without any issues, but the error is annoying.

Can I get rid of it?

  • 2
    Let's try to localize where the error is. If you type sudo -u postgres, do you get the same error? Sep 11, 2015 at 14:40
  • @MarkPlotnick is on the right track. There are too many things going on with your script to easily identify WHICH is causing the problem. However, the quick check would be to review permissions for user postgres on the folder /home/corey/scripts
    – 0xSheepdog
    Sep 11, 2015 at 14:48
  • 2
    I suspect it's simply because the OP ran the script from that directory, which the postgres user can't read, and the error would go away if the script was run from, say, /tmp. Sep 11, 2015 at 14:58

4 Answers 4


Postgres wants to create a $HOME/.psql_history file, where it will store all your queries and commands from the psql client. It may well want to do something else at $HOME, but I don't see any evidence in the form of other hidden files. And it won't actually create the history file unless you're using psql interactively, which you're not.

I had this exact same problem and found this question, but the accepted answer wasn't acceptable to me -- I shouldn't have to grant postgres permission to leave a trail of my queries in whatever directory I happen to be in when I run a script!

@Corey, the solution you mentioned in your comment (cd /tmp before calling sudo...) is probably the best. psql won't create this file in /tmp (I'm sure that's deliberate, because it could allow unprivileged users to read the file).

There are two other solutions I can think of :

  1. Run psql in a login shell by adding -i to your command

    sudo -i -u postgres psql < setup_dev_db.sql

    This will set $HOME to postgres's HOME directory, listed in /etc/passwd. For Ubuntu, that's /var/lib/postgres. But since you're piping in commands, it won't create a .psql_history file. However, if you use interactive psql, anyone else with sudo privileges on the machine will have access to your command history.

    I'm not sure if there are any other negative consequences to running a login shell in this situation.

  2. Run psql as a less-privileged user, e.g.

    $ psql dev_db -hlocalhost corey_dev -W < setup_dev_db.sql

    If this is a problem because you leave postgres user creation to your setup_dev_db.sql script, and you don't have any users yet, just add a createuser command in your script first, something like this:

    $ sudo -u postgres createuser corey_dev -P

    and perhaps ...

    $ sudo -u postgres createdb dev_db "Dev database"

NOTE: When using the psql client interactively (which you're not, here), if you see a message like could not change directory to "/home/corey/scripts": Permission denied message ****, psql is going to write to /var/lib/postgres/.psql_history (or wherever its $HOME is)! If you've ever seen that warning when using interactive psql, go look--you'll probably find a hidden history file.

  • I had to do sudo -u postgres -i psql -U .... because sudo -u -i postgres psql -U and sudo -ui postgres psql -U ... didn't work.
    – JL_SO
    Jan 12, 2022 at 15:35
  • I don't think that psql wanting to write to $HOME/.psql_history is the cause of this issue. In support of this suspicion I would like to offer the output of sudo -u postgres bash -c 'echo $HOME', which is /var/lib/postgresql; so writing to .psql_history should just work. No, for some reason,psql seems to insist on doing a chdir first to whatever the current working directory is, which for a non-interactive sudo will be the working directory of the invoker; hence the "could not change directory to /home/corey/scripts" output, which is unlikely to be someone's homedir.
    – cueedee
    Dec 15, 2023 at 14:46
  • However, if you do see your own homedirectory printed, then adding a --set-home flag to sudo will definitely print the homedir of the postgres user; but I will bet that, all other things considered equal, sudo --set-home -u postgres psql will still print the "could not change directory to ..." error.
    – cueedee
    Dec 15, 2023 at 14:54

To change to a directory, a user must have the 'x' permission for that directory.

I assume you are running the script from '/home/corey/scripts'. When 'sudo -u postgres' changes the current user to 'postgres' it attempts to set the working directory for 'postgres' to the working directory it was called from generating the error you're seeing.

Make sure that the user 'postgres' has permission 'x' for '/home/corey/scripts'.

  • I added "cd /tmp" to the top of my file and prefixed "setup_dev_db.sql" with "~/Dropbox/scripts/" and that fixed it.
    – Corey
    Sep 15, 2015 at 15:24

You may use sudo -u postgres -c your_command.bash or su postgres -c your_command.bash. You could also use,

su - postgres your_command.bash

This will ensure that you acquired all the postgres account enviroment.

  • won't work if you don't want everything in the script to run as root...
    – Lambart
    Oct 6, 2017 at 7:17

For me this did the trick, pay attention to quotes (')

sudo -Hiu postgres 'pg_dump --column-inserts --data-only --table=someTable entities_db > /var/backups/anywhere/$(date +%Y%m%d_%H%M%S)_someTable.sql'

Note the -Hiufor sudo, or use su - postgres

you can also put that in a cronjob for root with crontab -e

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .