find /var/cache/pacman/pkg/ -type f -ctime -30 -exec sh -c 'cp "$1" "/path/to/usb/$(basename $(echo "${1}" | sed 's/:/_colon_/'))"' sh_cp {} \;
to get it run inside quotes
#!/bin/bash
xfce4-terminal -x sh -c " ... "
"$1" becomes $"1"
"${1}" becomes ???
explanation: i’m trying to find/copy/rename all packages (those containing “:” included)
to a regular usb stick (FAT) in one step without using a temporary directory to rename them.
i just wanted to know how to get the find command into a bash script beginning with xfce4-terminal -x sh -c " ". the bash reference tells me nothing.
it’s a 353 lines script using select, different operations including command prompts, some find commands to show, count , copy and move pkgs. copying the ones without “:” works with
find /var/cache/pacman/pkg/ ! -name : -type f -daystart -ctime -30 -exec cp -nupt $USB_PATH {} + ;
but i cant rename them in one step. -execdir does not work, rename + basename neither.
i googled this and found a solution in my first post and i just need a proper substitution for the “${1}” expression.
I did not expect that you are such a DAU. I added echo for safety, so you can view the commands and check if they work correctly. And yes, an echo will not copy anything. I thought you are aware of such practice.
To use double-quotes inside double-quotes you should escape them see basics of quoting. eg:
"bla bla \"123\" blabla"
You need to protect the {} and ; from the shell because they are to be interpreted by the find command.
ALWAYS break-up lines and use indentations to make it readable and able to be followed to prevent errors when writing scripts !
The computer does not care but the human does…
Also escape special chars if you intend to pass them instead of being interpreted right away by the current shells.
Avoid sub-shells unless absolutely required, you could for example rewrite:
cp "$1" "/path/to/usb/$(basename $(echo "${1}" | sed 's/:/_colon_/'))"
Like this using only bash: (will be faster and avoids forking a new process)
I fail to understand the need for this colon conversion unless your USB filesystem can’t handle them like FAT, in which case you will have extra problems with name lengths also…
Avoid mixing different shell types as much as possible, ESPECIALLY inside a single command… That’s why i changed your sh invocations to bash versions…
And last but not least:
You pass sh_cp as FIRST argument to the shell executed by find, so you need to use $2 inside to grab the found filename.
You perform something inside a shell inside another shell inside yet another shell…
So you need to be very careful about used escapes that need tobe escaped themself…
Combining all the above would result in the below: (NOT TESTED, just applied what i wrote above while posting this reply)
Conclusion don’t try to do everything in one line or command, just use sub scripts (helper scripts) to perform actions to avoid problems caused by escape errors…
Just make sure your core action works, then call that core action as a helper script, it will allow you to debug problems MUCH easier…
IMHO, for the end purpose what you try to do, i would not let find execute commands but rather use the output and perform actions upon that output using one script…
The way you are trying to perform what you actually want as a result, is like reaching to your right ear using your left arm bend behind your head…
To be honest you won’t benefit much from the knowledge and experience of others with an attitude like that, we already have the knowledge and experience, it’s up to you to stay open to all kinds of reactions to be able to learn from them… (We are also humans and get aggravated on occasions)