I have search string in one variable ($AUD_DATE) and replace string in another variable ($YEST_DATE). I need to search file name in a folder using $AUD_DATE and then replace it with $YEST_DATE.
I tried using this link to do it but its not working with variables.
Find and replace filename recursively in a directory
shrivn1 $ AUD_DATE=140101
shrivn1 $ YEST_DATE=140124
shrivn1 $ ls *$AUD_DATE*
NULRL.PREM.DATA.CLRSFIFG.140101.dat NULRL.PREM.DATA.CLRTVEH.140101.dat
shrivn1 $ ls *$AUD_DATE*.dat | awk '{a=$1; gsub("$AUD_DATE","$YEST_DATE");printf "mv \"%s\" \"%s\"\n", a, $1}'
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140101.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140101.dat"
Actual output I need is
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140124.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140124.dat"
Thanks in advance
Approach 1
I generally create mv commands using sed and then pipe the output to sh. This approach allows me to see the commands that will be executed beforehand.
For example:
$ AUD_DATE=140101
$ YEST_DATE=140124
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}"
Once you are happpy with the output of the previous command;repeat it and pipe it's output to sh, like so:
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}" | sh
Approach 2
You could use xargs command.
ls -1tr | grep ${AUD_DATE}" | xargs -I target_file mv target_file target_file${YEST_DATE}
Related
My requirement is
localfolder=green.txt,yellow.txt,blue.txt
remotefolder=green_202105050333.txt,yellow_202105050333.txt,blue_202105050333.txt
I want to compare both folders as
IF[[localfolder==remotefolder]] ex: green.txt= green_202105050333.txt(here condition will look always first characters of each file or eliminating the data&time)
then
display the results as "matched"
kindly help me to get the logic here please.
Thanks in advance!!
You can do the next, create a file for each directory(folder), for example if you use ls :
# in local directory
ls localfolder > localFolder.txt
# in some remote directory
ls remoteFolder > remoteFolder.txt
We can suppose that files are the next:
localFolder.txt:
green.txt
yellow.txt
blue.txt
remoteFolder.txt:
green_202105050333.txt
yellow_202105050333.txt
blue_202105050333.txt
gray_202105050333.txt
Now put the files in the same directory and execute the next:
sed -r 's/\.[a-z]+//g' localFolder.txt | xargs -I{} grep {} remoteFolder.txt | sed -r 's/_[0-9]+//g'
The output will be:
green.txt
yellow.txt
blue.txt
Now if you want do it in script, then create a file for example myScript.sh and the content must be:
#!/bin/bash
sed -r 's/\.[a-z]+//g' $1 | xargs -I{} grep {} $2 | sed -r 's/_[0-9]+//g'
Give execution permissions to the script:
chmod +x myScript.sh
And executed like the next:
./diff.sh localFolder.txt remoteFolder.txt
You will have the same result.
This script only works for your case and this is an explain what do each part
# Remove .txt or any extensions for each line in localFolder
sed -r 's/\.[a-z]+//g' localFolder.txt
# The ouput of each line is received by grep and search in remoteFolder
| xargs -I{} grep {} remoteFolder.txt
# Remove the datetime
| sed -r 's/_[0-9]+//g'
What does this command do? Can it be shortened without losing functionality?
echo "abcabcabc" | sed "s/aBc/xyZ/gi;s/Z/a/;s/c/CCC/g" | xargs ls -ld
You would know what the command does if you entered it on a Mac OS terminal. It doesn't do anything but producing an error because the i in the sed command seems to be wrong or a typing error. However
echo "abcabcabc" | sed "s/aBc/xyZ/g;s/Z/a/;s/c/CCC/g" | xargs ls -ld
outputs the string abcabcabc which is used as input for the sed command which replaces aBc with xyZ, Z with a and c with CCC. This results in the string abCCCabCCCabCCC which is again input for the ls -ln command. If you had a file with the name abCCCabCCCabCCC in the current directory it would be found and it's details would be shown to you, otherwise the output is
ls: abCCCabCCCabCCC: No such file or directory
If it could be shortened depends on what you really want to achieve.
echo "abcabcabc" | sed "s/c/CCC/g" | xargs ls -ld
would have the same result in this case.
I search for some text in some file list. I have the following command to print these lines:
ls -1 *.log | xargs tail --lines=10000 | grep text_for_search
The command output contains all of occurrences of text_for_search, but it hasn't information from which file the occurrences are. How to modify the command to provide this information too?
Actually log files are gigabytes in size, so it's essential to use tail --lines=10000 for each of them
You could just use a loop instead, which will keep track of the file name for you:
for file in *.log; do
if tail --lines=-10000 "$file" | grep -q text_for_search; then
echo "$file"
fi
done
The -q switch to grep suppresses the output, returning a 0 (success) exit code if the pattern is matched.
You can use find command:
find . -name "*.log" -exec grep text_for_search '{}' \;
grep will output filename and matched line. If you just need filenames - add -l switch to grep command.
'{}' - macro used for matched file name substitution in find's -exec command,
\; indicates end of arguments for command, called by exec
Replace your tail command with:
awk '{v[NR]=$0}END{for(i=NR-10000;i<=NR;i++)print FILENAME,v[i]}'
This above is just the replacement of the tail command except it adds a file name in the begining of each line.
You must avoid parsing ls output and use shell's for loop to iterate through all *.log files:
for f in *.log; do
awk -v c=$(wc -l < "$f") 'NR>c-10000 && /text_for_search/{print FILENAME ":" $0}' "$f"
done
EDIT:
You can use awk to search through all *.log files:
awk 'NR>=10000 && /text_for_search/ {print FILENAME ":" $0}' *.log
I'm performing this
$ ls -l | awk '{print substr($9,substr1,11)}' | uniq | xargs -i ls {}*
ls: cannot access telneter.py*: No such file or directory
ls: cannot access telnetlib.p*: No such file or directory
ls: cannot access threading.p*: No such file or directory
I meant for it to search for files files* however it tells me that it cannot find the files because its actually looking for them with the actual * but i wanted to search for all files by * and not for files ending with *.
anyone can help with this please?
thanks
The * gets in too late to be interpreted by the shell. So, do it in a subshell.
ls -l | awk '{print substr($9,substr1,11)}' | uniq | xargs -i bash -c "ls {}*"
I'm trying to rename all files in current directory such that upper case name is converted to lower. I'm trying to do it like this:
ls -1|gawk '{print "`mv "$0" "tolower($0)"`"}'|xargs -i -t eval {}
I have two files in the directory, Y and YY
-t added for debugging, and output is:
eval `mv Y y`
xargs: eval: No such file or directory
if I execute the eval on its own, it works and moves Y to y.
I know there are other ways to achieve this, but I'd like to get this working if I can!
Cheers
eval is a shell builtin command, not a standalone executable. Thus, xargs cannot run it directly. You probably want:
ls -1 | gawk '{print "`mv "$0" "tolower($0)"`"}' | xargs -i -t sh -c "{}"
Although you're looking at an xargs solution, another method to perform the same thing can be done with tr (assuming sh/bash/ksh syntax):
for i in *; do mv $i `echo $i | tr '[A-Z]' '[a-z]'`; done
If your files are created by creative users, you will see files like:
My brother's 12" records
The solutions so far do not work on that kind of files. If you have GNU Parallel installed this will work (even on the files with creative names):
ls | parallel 'mv {} "$(echo {} | tr "[:upper:]" "[:lower:]")"'
Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ
You can use eval with xargs like the one below.
Note: I only tested this in bash shell
ls -1| gawk '{print "mv "$0" /tmp/"toupper($0)""}'| xargs -I {} sh -c "eval {}"
or
ls -1| gawk '{print "mv "$0" /tmp/"toupper($0)""}'| xargs -I random_var_name sh -c "eval random_var_name"
I generally use this approach when I want to avoid one-liner for loop.
e.g.
for file in $(find /some/path | grep "pattern");do somecmd $file; done
The same can be written like below
find /some/path | grep "pattern"| xargs -I {} sh -c "somecmd {}"