How is it possible to move/rename a file/directory using an Ansible module on a remote system? I don't want to use the command/shell tasks and I don't want to copy the file from the local system to the remote system.
The file module doesn't copy files on the remote system. The src parameter is only used by the file module when creating a symlink to a file.
If you want to move/rename a file entirely on a remote system then your best bet is to use the command module to just invoke the appropriate command:
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
If you want to get fancy then you could first use the stat module to check that foo actually exists:
- name: stat foo
stat: path=/path/to/foo
register: foo_stat
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
when: foo_stat.stat.exists
removes
option to the command
module (documented here)? It seems that that option would make Ansible check first. –
Geochemistry removes: /path/to/foo
and creates: /path/to/bar
. @Fonant already mentioned this as comment on another answer, but as this is the accepted one, I want to point it out again. –
Griffy removes: /path/to/foo
and creates: /path/to/bar
–
Carburetor test -f file && mv file file.old
. In that way mv
only would run when the file exists –
Sutlej From version 2.0, in copy module you can use remote_src
parameter.
If True
it will go to the remote/target machine for the src.
- name: Copy files from foo to bar
copy: remote_src=True src=/path/to/foo dest=/path/to/bar
If you want to move file you need to delete old file with file module
- name: Remove old files foo
file: path=/path/to/foo state=absent
From version 2.8 copy module remote_src
supports recursive copying.
command
module). –
Cytotaxonomy command: mv foo bar
for my use case. –
Matteson command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
–
Carburetor force: no
to copy to only copy if the dest
doesn't exist will fail if the source doesn't exist anymore, even it wouldn't need to copy as the dest
has already been created. –
Provincial The file module doesn't copy files on the remote system. The src parameter is only used by the file module when creating a symlink to a file.
If you want to move/rename a file entirely on a remote system then your best bet is to use the command module to just invoke the appropriate command:
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
If you want to get fancy then you could first use the stat module to check that foo actually exists:
- name: stat foo
stat: path=/path/to/foo
register: foo_stat
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
when: foo_stat.stat.exists
removes
option to the command
module (documented here)? It seems that that option would make Ansible check first. –
Geochemistry removes: /path/to/foo
and creates: /path/to/bar
. @Fonant already mentioned this as comment on another answer, but as this is the accepted one, I want to point it out again. –
Griffy removes: /path/to/foo
and creates: /path/to/bar
–
Carburetor test -f file && mv file file.old
. In that way mv
only would run when the file exists –
Sutlej I have found the creates option in the command module useful. How about this:
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
args:
creates: /path/to/bar
I used to do a two task approach using stat
like @Bruce P suggests. Now I do this as one task with creates
. I think this is a lot clearer.
command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
–
Skell test -f file && mv file file.old
–
Sutlej - name: Move the src file to dest
command: mv /path/to/src /path/to/dest
args:
removes: /path/to/src
creates: /path/to/dest
This runs the mv
command only when /path/to/src
exists and /path/to/dest
does not, so it runs once per host, moves the file, then doesn't run again.
I use this method when I need to move a file or directory on several hundred hosts, many of which may be powered off at any given time. It's idempotent and safe to leave in a playbook.
Another Option that has worked well for me is using the synchronize module . Then remove the original directory using the file module.
Here is an example from the docs:
- synchronize:
src: /first/absolute/path
dest: /second/absolute/path
archive: yes
delegate_to: "{{ inventory_hostname }}"
dest
is accessed through SSH even if the directory is on the same machine. –
Pruitt I know it's a YEARS old topic, but I got frustrated and built a role for myself to do exactly this for an arbitrary list of files. Extend as you see fit:
main.yml
- name: created destination directory
file:
path: /path/to/directory
state: directory
mode: '0750'
- include_tasks: move.yml
loop:
- file1
- file2
- file3
move.yml
- name: stat the file
stat:
path: {{ item }}
register: my_file
- name: hard link the file into directory
file:
src: /original/path/to/{{ item }}
dest: /path/to/directory/{{ item }}
state: hard
when: my_file.stat.exists
- name: Delete the original file
file:
path: /original/path/to/{{ item }}
state: absent
when: my_file.stat.exists
Note that hard linking is preferable to copying here, because it inherently preserves ownership and permissions (in addition to not consuming more disk space for a second copy of the file).
This is the way I got it working for me:
Tasks:
- name: checking if the file 1 exists
stat:
path: /path/to/foo abc.xts
register: stat_result
- name: moving file 1
command: mv /path/to/foo abc.xts /tmp
when: stat_result.stat.exists == True
the playbook above, will check if file abc.xts exists before move the file to tmp folder.
when: stat_result.stat.exists == True
. Just using when: stat_result.stat.exists
is good enough. –
Bonne == True
because I'm always doing something when the file is not found or == False
. –
Jp stat
module exists
property returns a boolean
value. So, if you only put when: stat_result.stat.exists
that will satisfy the condition if the file is present which is also identical for when: stat_result.stat.exists == True
but with more texts and unnecessary conditional check. –
Bonne Another way to achieve this is using file
with state: hard
.
This is an example I got to work:
- name: Link source file to another destination
file:
src: /path/to/source/file
path: /target/path/of/file
state: hard
Only tested on localhost (OSX) though, but should work on Linux as well. I can't tell for Windows.
Note that absolute paths are needed. Else it wouldn't let me create the link. Also you can't cross filesystems, so working with any mounted media might fail.
The hardlink is very similar to moving, if you remove the source file afterwards:
- name: Remove old file
file:
path: /path/to/source/file
state: absent
Another benefit is that changes are persisted when you're in the middle of a play. So if someone changes the source, any change is reflected in the target file.
You can verify the number of links to a file via ls -l
. The number of hardlinks is shown next to the mode (e.g. rwxr-xr-x 2, when a file has 2 links).
Bruce wasn't attempting to stat the destination to check whether or not to move the file if it was already there; he was making sure the file to be moved actually existed before attempting the mv.
If your interest, like Tom's, is to only move if the file doesn't already exist, I think we should still integrate Bruce's check into the mix:
- name: stat foo
stat: path=/path/to/foo
register: foo_stat
- name: Move foo to bar
command: creates="path/to/bar" mv /path/to/foo /path/to/bar
when: foo_stat.stat.exists
This may seem like overkill, but if you want to avoid using the command module (which I do, because it using command is not idempotent) you can use a combination of copy and unarchive.
- Use tar to archive the file(s) you will need. If you think ahead this actually makes sense. You may want a series of files in a given directory. Create that directory with all of the files and archive them in a tar.
- Use the unarchive module. When you do that, along with the destination: and remote_src: keyword, you can place copy all of your files to a temporary folder to start with and then unpack them exactly where you want to.
On Windows:
- name: Move old folder to backup
win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"
To rename use rename or ren command instead
You can Do It by --
Using Ad Hoc Command
ansible all -m command -a" mv /path/to/foo /path/to/bar"
Or You if you want to do it by using playbook
- name: Move File foo to destination bar
command: mv /path/to/foo /path/to/bar
to copy/move/rename any file we can use shell or command module
- name: copy or mv within remote host command: cp /path/of/the/file/with/name /path/of/the/destination/directory/
while giving source make sure name of the file is last with no slash(/) and destination ends with slash(/)
- name: rename within remote host shell: chdir=/path/ mv file_name new_file_name
command and shell and be used interchangeably.
- name: Example
hosts: localhost
become: yes
tasks:
- name: checking if a file exists
stat:
path: "/projects/challenge/simplefile.txt"
register: file_data
- name: move the file if file exists
copy:
src: /projects/challenge/simplefile.txt
dest: /home/user/test
when: file_data.stat.exists
- name: report a missing file
debug:
msg: "the file or directory doesn't exist"
when: not file_data.stat.exists
© 2022 - 2024 — McMap. All rights reserved.