Ant target to move directories out of another directory - file

What is the simplest way to move everything out of a target directory?
I have this basedir/parentdir/<subdir>. I have many different <subdir>. I need to move them out into the same level as parentdir so that it becomes basedir/<subdir>. Now, each <subdir> contains a deep tree of many other subdirectories and files, including empty subdirectories.
I've tried the following:
<move todir="basedir">
<fileset dir="parentdir">
<include name="**/*.*" />
</fileset>
</move>
That failed to move the empty directories - meaning after the move, all the <subdir> are missing their empty subdirectories. "move" supposedly copies emptysubdirectories by default, so I tried the following next:
<move todir="basedir">
<fileset dir="parentdir">
<include name="**/*" />
<include name="**/*.*" />
</fileset>
</move>
While I did manage to move the empty subdirectories, the strange thing is that all the immediate subdirectories of all the <subdir> gets copied into basedir. Every <subdir> has src, test, and build. These are now sitting in basedir as well as in their original moved <subdir>.
I'm positive I'm doing something wrong but I don't know what. Am I approaching things the wrong way?

Try this
<project name="moveproject" basedir="." default="moveDirs">
<target name="moveDirs">
<move todir="${basedir}" includeEmptyDirs="yes" verbose="true">
<fileset dir="parentdir" >
<include name="**/*" />
</fileset>
</move>
</target>
</project>

Related

Ant task to find all sub-directories that contain a certain file

I'm struggling to figure out this task in Ant. There are not many examples in the documentation and I can;t seem to find a solid answer online.
I need to scan a directory that contains several sub-directories eg
Root
TargetFolder
Folder A
Folder B
Folder C
...
Folder Z
I need to run the build.xml from Root, and with a task scan all sub-directories of TargetFolder (so Folder A, B, C etc) and if the directory contains a file, foo.txt, run an <apply> task for that directory.
I'm able to do a <dirset> and get the list of sub-directories. And I can do a separate <fileset> to scan TargetFolder and get all occurences of foo.txt. But, I have no clue how to combine these things, or how to go about doing a simple file check attached to the <apply> task.
Here is one way. Use a dirset as you say, with the <present> selector:
<dirset id="dirs" dir="Root">
<present targetdir="Root">
<mapper type="glob" from="*" to="*/foo.txt" />
</present>
</dirset>
<apply executable="ls">
<arg value="-alF" />
<dirset refid="dirs" />
</apply>
You could merge both into one task:
<apply executable="ls">
<arg value="-alF" />
<dirset id="dirs" dir="Root">
<present targetdir="Root">
<mapper type="glob" from="*" to="*/foo.txt" />
</present>
</dirset>
</apply>

Rename files in a directory based on other directory

I'm having several outputs of a program that I need to compare with a "expected" ouput folder. But my problem is that the output files always have a different filename.
How can I rename all files in a folder to the same filenames in another folder. Here the example - the expected file structure (can of course change):
expected/folder1/file1.txt
expected/folder1/file2.txt
expected/folder2/file1.txt
expected/folder3/file1.txt
And my output looks like this (number of files and position is always equal):
result/folder1/fileOtherName1.txt
result/folder1/fileOtherName2.txt
result/folder2/fileOtherName1.txt
result/folder3/fileOtherName1.txt
I tried using ANT (because I know that), but was stuck, because I cannot select a file by the index (sorted alphabetically).
Here my pseudocode in ANT (but don't know how to continue):
<target name="foo">
<foreach>
<fileset dir="result" casesensitive="yes">
<include name="**/*.txt"/>
</fileset>
<antcall target="rename">
</antcall>
</foreach>
</target>
<target name="rename">
<!-- how can I access another fileset and take the correct file? -->
<!-- Here I got stuck -->
<echo message="foreach.file is ${foreach.file}" />
<echo message="foreach.dir is ${foreach.dir}" />
<echo message="foreach.name.ext is ${foreach.name.ext}" />
<echo message="foreach.name is ${foreach.name}" />
</target>
Thanks for any help, it must not be in ANT only - a BASH script or similar could do the job too.
How about
#!/bin/bash
IN_DIR="expected/folder1"
OUT_DIR="result/folder2"
IN_FILES=($IN_DIR/*)
OUT_FILES=($OUT_DIR/*)
for ((i=0; i<${#IN_FILES[#]}; i++)); do
mv ${OUT_FILES[i]} $OUT_DIR/$(basename ${IN_FILES[i]})
done
Tested it on some test dirs, and it works OK.
Note that if any of your file names contains a space, it does not work.
I personally don't know ANT, so I'll give it a shot in bash.
for i in *; do
k=1;
for j in $i/*; do
mv "$j" $i/file$k.txt;
k=$[$k+1];
done;
done
This iterates through the folders and increments a counter for every file in the folder. When we proceed to the next folder, the counter is reset.
I created a test directory structure like yours and it worked for me.

Concatenating Files - Including files in folders

I currently have this command:
copy /b *.txt newfile.txt
But I want to include all files with folders as well.
How can I do this? Is it possible to add this to Apache Ant as well?
I also consider doing this to minify JS files.
Im using windows and would like a command to run or batch file but having issues.
Is there anyway to remove lines as well?
Is there a better command to use than the one I am currently using?
UPDATE:
<target name="concatenate" description="Concatenate all js files">
<concat destfile="build/application.js">
<fileset dir="js" includes="*.js" />
</concat>
</target>
<target name="compress" depends="concatenate" description="Compress application.js to application-min.js">
<apply executable="java" parallel="false">
<filelist dir="build" files="application.js" />
<arg line="-jar" />
<arg path="C:\yuicompressor-2.4.7\build\yuicompressor-2.4.7.jar" />
<srcfile />
<arg line="-o" />
<mapper type="glob" from="*.js" to="build/*-min.js" />
<targetfile />
</apply>
Now i am using the above code but cant get it to include files within folders
As oers pointed out in the comment, Ant patterns use ** to recursively match directories. Here is the relevant Patterns section from the Ant manual:
To make things a bit more flexible, we add one extra feature, which makes it possible to match multiple directory levels. This can be used to match a complete directory tree, or a file anywhere in the directory tree. To do this, ** must be used as the name of a directory. When ** is used as the name of a directory in the pattern, it matches zero or more directories. For example: /test/** matches all files/directories under /test/, such as /test/x.java, or /test/foo/bar/xyz.html, but not /xyz.xml.
There is one "shorthand": if a pattern ends with / or \, then ** is appended. For example, mypackage/test/ is interpreted as if it were mypackage/test/**.
The "concatenate" target above would be:
<target name="concatenate" description="Concatenate all js files">
<concat destfile="build/application.js">
<fileset dir="js" includes="**/*.js" excludes="**/*.min.js" />
</concat>
</target>

Last write time of directory or fileset in NAnt

NAnt has directory::get-last-write-time and file::get-last-write-time, but I am looking for a way to get the time of the most recent write of any file in a directory (recursively) or fileset.
directory::get-last-write-time might seem useful, but it only gets updated if a file directly in the directory gets written to, not for a file within a sub-directory.
Is there any way to do this with stock NAnt or would I have to write something that recurses over all the contents of a directory/fileset and finds the most recent write time?
You can do this with NAnt using a plain old <foreach> loop. A little bit awkward but it works:
<target name="go">
<fileset
id="paths"
basedir="C:\foo">
<include name="**/*" />
</fileset>
<!-- preset with Unix epoch -->
<property
name="most.recent"
value="1970-01-01T00:00:00Z" />
<foreach item="File" property="path">
<in>
<items refid="paths" />
</in>
<do>
<property
name="current"
value="${file::get-last-write-time(path)}" />
<property
name="most.recent"
value="${current}"
if="${datetime::parse(current) > datetime::parse(most.recent)}" />
</do>
</foreach>
<echo message="${most.recent}" />
</target>

How to create a file in distributed system using ant script?

i am working with mqfte. i have to create a empty txt file with the same name as the source file after it is transferred to the destination. How can do this using ant script?
Scenario:
Srcpath: \src\test.dat
destpath: \dest\test.dat
After the file is moved from src path, i need to create a empty file test.dat in the src path using ant script? how can this be done?
Before you transfer the files, you could use the Touch task to create the new empty files matching those you will be transferring (reuse the same fileset) in a temporary directory. After the transfers are complete, you could use the Move task to copy the empty files into your src dir. You could use overwrite="false" in the Move task to ensure that files remaining in the src dir do not get replaced (e.g. if you wanted to be sure to have empty files only for successful transfers).
Here is an example.
<project default="test">
<target name="test">
<touch>
<fileset dir="src">
<include name="test*"/>
</fileset>
<mapper type="regexp" from="(.*)" to="tmp/\1"/>
</touch>
<move todir="dest">
<fileset dir="src">
<include name="test*"/>
<!-- simulate file not transferred -->
<exclude name="test.doc"/>
</fileset>
<globmapper from="test.*" to="result_*.txt"/>
</move>
<move todir="src" overwrite="false">
<fileset dir="tmp"/>
</move>
</target>
</project>
The first move stands in for your transfer. One file (test.doc) is not moved out of the src dir (simulate failed transfer). You can test be creating files with some content in the src dir. After the target completes, the test.doc should still have its original content. The other files should be empty.
In response to your question about the regexp mapper:
<mapper type="regexp" from="(.*)" to="tmp/\1"/>
This captures the whole of the incoming file name into a group...
from="(.*)"
and prepends "tmp/" to that captured group...
to="tmp/\1"
(In regular expression \1 refers to the first captured group in the expression. Groups are defined using parentheses.)
So from src/somefile.txt, we will get somefile.txt as the input file to the mapper, and we translate this to tmp/somefile.txt.

Resources