So I need to write a bash script that copies all files to a specified directory however I need to rename the files to it's absolute path by replacing the / character with __.

For example if the file zad1.sh is in the directory /home/123456/ the file needs to be renamed to __home__123456__zad1.sh

Any ideas on how to do this?

  • all files - from where? Add some pseudo-code – RomanPerekhrest Jun 14 at 15:33
  • Please, show us what you tried so far. – andcoz Jun 14 at 15:34
  • 4
    Presuming this is for something, how are you going to handle the case of some__really__important_file.txt when putting things back not going into /path/to/some/really/important_file.txt? – DopeGhoti Jun 14 at 15:40
  • 2
    @DopeGhoti Good point. For example Python projects might have files named __init__.py, __main__.py, etc. – wjandrea Jun 14 at 20:05
up vote -1 down vote accepted

The classic approach would be to use sed:

cp "${filename}" "$(realpath ${filename} | sed s:/:__:g)"

The advantage is primarily portability across shells if you won't necessarily always be using bash.

Of course, it also lets you forego the script and just do it with find:

find /base/path -type f -exec cp \{\} `realpath \{\} | sed s:/:__:g` \;

Find has sorting and filtering options you can use if you need them to only copy certain files.

edit: That find setup works on one of my systems, but not on the other one. Rather than sort out the difference, I just made it more portable:

find /base/path -type f | sed -e "p; s:/:__:g" | xargs -n2 cp
  • 5
    That find command will not work. The backticks will be evaluated before find and get you basically the equivalent of $PWD/{} with the slashes in $PWD replaced with double underscores. So, if you're in /home/user, this is equivalent to: find /base/path -exec cp {} __home__user__{} \; If you have a file f in /base/path, this will try to copy it to __home__user__/base/path/f. – JoL Jun 14 at 21:04
  • @JoL It worked when I tested it... I'll test it again when I get a few minutes... – Perkins Jun 17 at 3:47
  • find -exec sh -c 'cp "$1" "$(realpath "$1" | sed s:/:__:g)"' sh {} \; should do – ilkkachu Jun 17 at 17:18
  • xargs will have issues with names with whitespace, unless you use find -print0 | sed -z | xargs -0 (with at least GNU sed). Also any of those will make the copies to the current directory, which may or may not be what you want. – ilkkachu Jun 17 at 17:22
  • 1
    @Perkins "That find setup works on one of my systems" I have a hard time imagining how that could work anywhere. The only edge case I can kind of see is if your current working directory is /base/path and you just have regular files in there, no directories. However, even then you'd be copying to e.g. /base/path/__base__path__./f. That's not right. – JoL Jun 18 at 3:16

To get the path of your file :

realpath <file>

Replace in bash:

echo "${var//search/replace}"

The first two slashes are for making global search. Using just / would only do one replacement.

So your code could be

path=$(realpath zad1.sh)
path_replaced=${path//\//__}

I believe this will accomplish what you are asking:

#!/bin/bash

_from_dir=/path/to/files
_to_dir=/path/to/dest

for file in "${_from_dir}/"*; do
    nfile="$(sed 's#/#__#g' <<<"$file")"
    cp "$file" "${_to_dir}/$nfile"
done

Set the _from_dir variable to the path where your files are located and the _to_dir variable to the path where you want them copied.

The loop will go through each file in the _from_dir location. nfile will take the full path of the file and replace / with __. Then it will cp the file into the _to_dir path with a name representing the full path of it's origin.

I have done by below method

ls -ltr /root/l.txt| awk '{print "cp" " " $NF,$NF}'| awk '{gsub("/","_",$NF);print $1,$2,"/root/p1/"$3}'| sh

Here file /root/l.txt will be copied to /root/p1/ path but filename will be _root_l.txt Let me know for any confusion

Here /root/p1==> destination path

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.