diff --git a/src/color_ssh/color_ssh.py b/src/color_ssh/color_ssh.py
index 0534891..294a553 100644
--- a/src/color_ssh/color_ssh.py
+++ b/src/color_ssh/color_ssh.py
@@ -21,6 +21,9 @@ class Setting(object):
         '       %prog [options...] -H "[user@]hostname [[user@]hostname]...]" command'
     ])
     DEFAULT_PARALLELISM = 32
+    CMD_SSH = str('ssh')
+    CMD_UPLOAD = [str('rsync'), str('-a')]
+    CMD_MKDIR = [str('mkdir'), str('-p')]
 
     def __init__(self, parallelism=None, tasks=None):
         self.parallelism = parallelism
@@ -39,7 +42,7 @@ class Setting(object):
             help='label name'
         )
         parser.add_option(
-            '--ssh', dest='ssh', default=str('ssh'), type='string', metavar='SSH',
+            '--ssh', dest='ssh', default=self.CMD_SSH, type='string', metavar='SSH',
             help='override ssh command line string'
         )
         parser.add_option(
@@ -62,11 +65,16 @@ class Setting(object):
             '--upload', dest='upload', default=False, action='store_true',
             help='upload files before executing a command (all args are regarded as paths)'
         )
+        parser.add_option(
+            '--upload-with', dest='upload_with', default=None, type='string', metavar='PATH',
+            help='file paths to be uploaded before executing a command'
+        )
 
         option, args = parser.parse_args(argv[1:])
         hosts = self._load_hosts(option.host_file) + (option.host_string.split() if option.host_string else [])
 
         if len(args) < (1 if hosts else 2):
+            print(option.__dict__)
             stdout.write(arg2bytes(parser.format_help().encode('utf-8')))
             parser.exit(2)
 
@@ -77,6 +85,9 @@ class Setting(object):
         # parse hosts
         parsed_hosts = [self._parse_host(h) for h in hosts]
 
+        # parse upload-with option
+        upload_with = [] if option.upload_with is None else shlex.split(option.upload_with)
+
         tasks = []
         if option.distribute:
             # distribute args
@@ -84,24 +95,16 @@ class Setting(object):
             d = distribute(len(hosts), args)
             for i, (user, host, port) in enumerate(parsed_hosts):
                 if d[i]:
-                    setup_commands = []
-                    if option.upload:
-                        # create directories
-                        dirs = list(set(x for x in [os.path.dirname(arg) for arg in d[i]] if x != '' and x != '.'))
-                        if dirs:
-                            setup_commands.append(
-                                self._ssh_args(option.ssh, user, host, port) + [str('mkdir'), str('-p')] + dirs
-                            )
-
-                        # upload files before executing main commands
-                        setup_commands.extend([self._scp_args(str('rsync -a'), user, host, port, arg) for arg in d[i]])
-
+                    upload_paths = upload_with + d[i] if option.upload else []
                     label = option.label or host
                     ssh_args = self._ssh_args(option.ssh, user, host, port)
-                    tasks.append((label, ssh_args + dist_prefix + d[i], setup_commands))
+                    tasks.append((label, ssh_args + dist_prefix + d[i],
+                                  self._build_upload_commands(user, host, port, option.ssh, upload_paths)))
         else:
             for user, host, port in parsed_hosts:
-                tasks.append((option.label or host, self._ssh_args(option.ssh, user, host, port) + args, []))
+                tasks.append((option.label or host,
+                              self._ssh_args(option.ssh, user, host, port) + args,
+                              self._build_upload_commands(user, host, port, option.ssh, upload_with)))
 
         self.parallelism = option.parallelism
         self.tasks = tasks
@@ -140,12 +143,25 @@ class Setting(object):
             [] if port is None else [str('-p'), port]) + [Setting._build_host_string(user, host)]
 
     @staticmethod
-    def _scp_args(scp_cmd, user, host, port, path):
-        return shlex.split(scp_cmd) + ([] if port is None else [str('-P'), port]) + [
+    def _upload_args(user, host, port, path):
+        return Setting.CMD_UPLOAD + ([] if port is None else [str('-P'), port]) + [
             path,
             Setting._build_host_string(user, host) + str(':') + path
         ]
 
+    @staticmethod
+    def _build_upload_commands(user, host, port, ssh_cmd, paths):
+        # create directories
+        dirs = list(set(x for x in [os.path.dirname(path) for path in paths] if x != '' and x != '.'))
+
+        ret = []
+        if dirs:
+            ret.append(Setting._ssh_args(ssh_cmd, user, host, port) + Setting.CMD_MKDIR + sorted(dirs))
+
+        # upload files
+        ret.extend([Setting._upload_args(user, host, port, path) for path in paths])
+        return ret
+
 
 def run_task(args):
     label, command, setup_commands = args

Add upload-with option
diff --git a/tests/color_ssh/test_color_ssh.py b/tests/color_ssh/test_color_ssh.py
index 2c22fee..ccb7c34 100644
--- a/tests/color_ssh/test_color_ssh.py
+++ b/tests/color_ssh/test_color_ssh.py
@@ -115,6 +115,35 @@ class TestSetting(TestCase):
                  [['rsync', '-a', 'z', 'root@server-12:z']]),
             ])
 
+        # upload-with
+        self._check(self._parse(['--upload-with=dir1/x', 'server-1', 'pwd']),
+                    [('server-1', ['ssh', 'server-1', 'pwd'], [
+                        ['ssh', 'server-1', 'mkdir', '-p', 'dir1'],
+                        ['rsync', '-a', 'dir1/x', 'server-1:dir1/x'],
+                    ])])
+
+        self._check(
+            self._parse([
+                '--upload-with', 'dir2/c dir2/d dir3/e',
+                '-H', 'server-11 root@server-12', '--distribute', 'echo "foo bar"', '--upload', 'dir1/x', 'dir1/y', 'z'
+            ]), [
+                ('server-11', ['ssh', 'server-11', 'echo', 'foo bar', 'dir1/x', 'dir1/y'], [
+                    ['ssh', 'server-11', 'mkdir', '-p', 'dir1', 'dir2', 'dir3'],
+                    ['rsync', '-a', 'dir2/c', 'server-11:dir2/c'],
+                    ['rsync', '-a', 'dir2/d', 'server-11:dir2/d'],
+                    ['rsync', '-a', 'dir3/e', 'server-11:dir3/e'],
+                    ['rsync', '-a', 'dir1/x', 'server-11:dir1/x'],
+                    ['rsync', '-a', 'dir1/y', 'server-11:dir1/y']
+                ]),
+                ('server-12', ['ssh', 'root@server-12', 'echo', 'foo bar', 'z'], [
+                    ['ssh', 'root@server-12', 'mkdir', '-p', 'dir2', 'dir3'],
+                    ['rsync', '-a', 'dir2/c', 'root@server-12:dir2/c'],
+                    ['rsync', '-a', 'dir2/d', 'root@server-12:dir2/d'],
+                    ['rsync', '-a', 'dir3/e', 'root@server-12:dir3/e'],
+                    ['rsync', '-a', 'z', 'root@server-12:z']
+                ]),
+            ])
+
     def test_parse_args_error(self):
         with self.withBytesOutput() as (out, err):
             self.assertSystemExit(2, Setting().parse_args, ['color-ssh'], out)

pip install -e .[dev]
parse_log_pytest
pytest
pytest pytest-cov six mog-commons>=0.2.2
3.5
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
-e git+https://github.com/mogproject/color-ssh.git@881561051ebae23a03aec3063877ee1cf21e24c0#egg=color_ssh
coverage==6.2
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.0.3
MarkupSafe==2.0.1
mog-commons==0.2.3
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
pytest-cov==4.0.0
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==1.2.3
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: color-ssh
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==6.2
      - jinja2==3.0.3
      - markupsafe==2.0.1
      - mog-commons==0.2.3
      - pytest-cov==4.0.0
      - six==1.17.0
      - tomli==1.2.3
prefix: /opt/conda/envs/color-ssh

tests/color_ssh/test_color_ssh.py::TestSetting::test_parse_args
tests/color_ssh/test_color_ssh.py::TestSetting::test_parse_args_error tests/color_ssh/test_color_ssh.py::TestSetting::test_parse_host_error tests/color_ssh/test_color_ssh.py::TestMain::test_main_load_error tests/color_ssh/test_color_ssh.py::TestMain::test_main_multi_proc tests/color_ssh/test_color_ssh.py::TestMain::test_main_single_proc tests/color_ssh/test_color_ssh.py::TestMain::test_main_task_error tests/color_ssh/test_color_ssh.py::TestMain::test_run_task_error
src/color_ssh/color_ssh.py
src/color_ssh/color_ssh.py