diff --git a/lib/rake/file_utils.rb b/lib/rake/file_utils.rb
index 1510d95c3..c52091715 100644
--- a/lib/rake/file_utils.rb
+++ b/lib/rake/file_utils.rb
@@ -48,7 +48,7 @@ def sh(*cmd, &block)
     verbose = options.delete :verbose
     noop    = options.delete(:noop) || Rake::FileUtilsExt.nowrite_flag
 
-    Rake.rake_output_message sh_show_command cmd if verbose
+    Rake.rake_output_message sh_show_command(cmd, options) if verbose
 
     unless noop
       res = (Hash === cmd.last) ? system(*cmd) : system(*cmd, options)
@@ -68,7 +68,7 @@ def create_shell_runner(cmd) # :nodoc:
   end
   private :create_shell_runner
 
-  def sh_show_command(cmd) # :nodoc:
+  def sh_show_command(cmd, options = nil) # :nodoc:
     cmd = cmd.dup
 
     if Hash === cmd.first
@@ -77,7 +77,12 @@ def sh_show_command(cmd) # :nodoc:
       cmd[0] = env
     end
 
-    cmd.join " "
+    cmd = cmd.join " "
+    if options and chdir = options[:chdir]
+      "(cd #{chdir} && #{cmd})"
+    else
+      cmd
+    end
   end
   private :sh_show_command
 
diff --git a/test/helper.rb b/test/helper.rb
index 7ef6e6958..619bf42c7 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -27,7 +27,7 @@ class TaskManager
     include Rake::TaskManager
   end
 
-  RUBY = File.realpath(ENV["RUBY"] || Gem.ruby)
+  RUBY = (ENV["RUBY"] || Gem.ruby)
 
   def setup
     ARGV.clear
@@ -124,5 +124,9 @@ def jruby9?
     jruby? && (JRUBY_VERSION >= "9.0.0.0")
   end
 
+  def jruby90?
+    jruby? && JRUBY_VERSION.start_with?("9.0.")
+  end
+
   include RakefileDefinitions
 end
diff --git a/test/test_rake_file_utils.rb b/test/test_rake_file_utils.rb
index 3af5e96f1..36500be8b 100644
--- a/test/test_rake_file_utils.rb
+++ b/test/test_rake_file_utils.rb
@@ -182,7 +182,7 @@ def test_sh_with_multiple_arguments
   end
 
   def test_sh_with_spawn_options
-    omit "JRuby does not support spawn options" if jruby?
+    omit "JRuby does not support spawn options" if jruby90?
 
     echocommand
 
@@ -240,10 +240,24 @@ def test_sh_noop
     assert true, "should not fail"
   end
 
+  def test_sh_chdir
+    omit "JRuby does not support spawn options" if jruby90?
+
+    Dir.mkdir "chdir_test"
+    out, err = capture_output do
+      verbose(true) {
+        sh "echo ok", chdir: "chdir_test", verbose: true, noop: true
+      }
+    end
+
+    assert_equal "(cd chdir_test && echo ok)\n", err
+    assert_empty out
+  end
+
   def test_sh_bad_option
     # Skip on JRuby because option checking is performed by spawn via system
     # now.
-    omit "JRuby does not support spawn options" if jruby?
+    omit "JRuby does not support spawn options" if jruby90?
 
     shellcommand
 
@@ -388,7 +402,7 @@ def assert_echoes_fully
   end
 
   def test_ruby_with_multiple_arguments
-    omit if jruby9? # https://github.com/jruby/jruby/issues/3653
+    omit if jruby90? # https://github.com/jruby/jruby/issues/3653
 
     check_no_expansion